计算元组大小
Calculate tuple size
我试图了解列顺序如何最小化 PostgreSQL 中的 table 大小。
示例:
CREATE TABLE test (
column_1 int
,column_2 int
,column_3 bigint
,column_4 bigint
,column_5 text
,column_6 text
,column_7 numeric(5,2)
,column_8 numeric(5,2)
,column_9 timestamp
,column_10 boolean
,column_11 boolean
);
INSERT INTO test
VALUES(1,1,1,1,'test','test_1',12,12,current_timestamp,true,false);
SELECT pg_column_size(test.*) FROM test;
pg_column_size
----------------
82
(1 row)
元组大小:
元组头的 23 字节开销 + NULL 位图的 1 字节,因此:
24+4+4+8+8+5+7+5+5+8+1+1=80 但实际的元组大小是 82。
有没有2字节的额外开销?
我理解下面给出的例子 link:
Calculating and saving space in PostgreSQL
如果我们删除 column_8 numeric(5,2)
那么元组大小也保持不变,即:82.
我已重新排序 table 以最小化元组大小并给出 80。
CREATE TABLE test (
column_3 bigint
,column_4 bigint
,column_9 timestamp
,column_1 int
,column_2 int
,column_10 boolean
,column_11 boolean
,column_7 numeric(5,2)
,column_8 numeric(5,2)
,column_5 text
,column_6 text);
INSERT INTO test
VALUES(1,1,current_timestamp,1,1,true,false,12,12,'test','test_1');
SELECT pg_column_size(test) FROM test;
pg_column_size
----------------
80
对于 PostgreSQL 中的列顺序有什么建议吗?
您在 column_9 timestamp
之前错过了另外 2 个字节的填充,它需要从 8 个字节的倍数开始。
24+4+4+8+8+5+7+5+5+8+1+1=80 but the actual tuple size is 82.
------------------^ <----- 2 bytes of padding here
也是这个原因:
If we remove the column_8 numeric(5,2)
then also the tuple size
remains the same, i.e.: 82.
取出占用 5 个字节的列后,您会在同一位置得到 7 个字节的填充 - 最坏的情况。
另请注意,这一行实际上在磁盘上占用 88 字节,因为下一个元组的元组头是左对齐的(从 MAXALIGN
的倍数开始,通常为 8 个字节)。
您修改后的行以 8 字节的倍数结尾,不会产生额外的填充,只需要 80 个字节。
不过,两者都需要另外 4 个字节用于页眉中的元组指针。
这是一个 "column tetris" 的游戏,你似乎已经了解了它的基础知识。通常你不会得到太多,不要想太多。不过,也有极端的极端情况。空值改变游戏 每行 .
您需要了解每种数据类型的大小、对齐和填充要求以及 NULL 位图的特殊规则。
- Do nullable columns occupy additional space in PostgreSQL?
dba.SE上详细计算的相关答案:
这在 MS-SQL 中使用 sys.objects
和 sys.columns
计算非常简单,我相信 PostgreSQL 中一定有一些类似的解决方案:
/* Total Size of Tuple */
select
sum(c.max_length) [Total Tuple Size]
from sys.columns c
inner join sys.objects o on c.object_id = o.object_id
inner join sys.types t on c.user_type_id = t.user_type_id
where
o.name = 'your-table-name'
/* Column wise byte size */
select
c.name [Column Name]
,t.name [Type]
,c.max_length [Maximum Length in Bytes]
from sys.columns c
inner join sys.objects o on c.object_id = o.object_id
inner join sys.types t on c.user_type_id = t.user_type_id
where
o.name = 'your-table-name'
order by c.column_id
我试图了解列顺序如何最小化 PostgreSQL 中的 table 大小。
示例:
CREATE TABLE test (
column_1 int
,column_2 int
,column_3 bigint
,column_4 bigint
,column_5 text
,column_6 text
,column_7 numeric(5,2)
,column_8 numeric(5,2)
,column_9 timestamp
,column_10 boolean
,column_11 boolean
);
INSERT INTO test
VALUES(1,1,1,1,'test','test_1',12,12,current_timestamp,true,false);
SELECT pg_column_size(test.*) FROM test;
pg_column_size
----------------
82
(1 row)
元组大小:
元组头的 23 字节开销 + NULL 位图的 1 字节,因此:
24+4+4+8+8+5+7+5+5+8+1+1=80 但实际的元组大小是 82。
有没有2字节的额外开销?
我理解下面给出的例子 link:
Calculating and saving space in PostgreSQL
如果我们删除 column_8 numeric(5,2)
那么元组大小也保持不变,即:82.
我已重新排序 table 以最小化元组大小并给出 80。
CREATE TABLE test (
column_3 bigint
,column_4 bigint
,column_9 timestamp
,column_1 int
,column_2 int
,column_10 boolean
,column_11 boolean
,column_7 numeric(5,2)
,column_8 numeric(5,2)
,column_5 text
,column_6 text);
INSERT INTO test
VALUES(1,1,current_timestamp,1,1,true,false,12,12,'test','test_1');
SELECT pg_column_size(test) FROM test;
pg_column_size
----------------
80
对于 PostgreSQL 中的列顺序有什么建议吗?
您在 column_9 timestamp
之前错过了另外 2 个字节的填充,它需要从 8 个字节的倍数开始。
24+4+4+8+8+5+7+5+5+8+1+1=80 but the actual tuple size is 82. ------------------^ <----- 2 bytes of padding here
也是这个原因:
If we remove the
column_8 numeric(5,2)
then also the tuple size remains the same, i.e.: 82.
取出占用 5 个字节的列后,您会在同一位置得到 7 个字节的填充 - 最坏的情况。
另请注意,这一行实际上在磁盘上占用 88 字节,因为下一个元组的元组头是左对齐的(从 MAXALIGN
的倍数开始,通常为 8 个字节)。
您修改后的行以 8 字节的倍数结尾,不会产生额外的填充,只需要 80 个字节。
不过,两者都需要另外 4 个字节用于页眉中的元组指针。
这是一个 "column tetris" 的游戏,你似乎已经了解了它的基础知识。通常你不会得到太多,不要想太多。不过,也有极端的极端情况。空值改变游戏 每行 .
您需要了解每种数据类型的大小、对齐和填充要求以及 NULL 位图的特殊规则。
- Do nullable columns occupy additional space in PostgreSQL?
dba.SE上详细计算的相关答案:
这在 MS-SQL 中使用 sys.objects
和 sys.columns
计算非常简单,我相信 PostgreSQL 中一定有一些类似的解决方案:
/* Total Size of Tuple */ select sum(c.max_length) [Total Tuple Size] from sys.columns c inner join sys.objects o on c.object_id = o.object_id inner join sys.types t on c.user_type_id = t.user_type_id where o.name = 'your-table-name'
/* Column wise byte size */ select c.name [Column Name] ,t.name [Type] ,c.max_length [Maximum Length in Bytes] from sys.columns c inner join sys.objects o on c.object_id = o.object_id inner join sys.types t on c.user_type_id = t.user_type_id where o.name = 'your-table-name' order by c.column_id