行大小的计算要复杂得多.
存储通常以8KB data pages进行分区.每页有一个小的固定开销,可能的余数不足以容纳另一个元组,更重要的是,死行或最初保留的百分比设置为FILLFACTOR
.
还有更大的开销per row(元组):页面开头的项标识符为4字节,HeapTupleHeader
为23字节,alignment padding为alignment padding字节.元组头的开头和元组数据的开头以MAXALIGN
的倍数对齐,在典型的64位机器上是8字节.有些数据类型需要与下一个2、4或8字节的倍数对齐.
Quoting the manual on the system table pg_tpye
:
typalign
是存储此类型的值时所需的对齐方式.
可能的值包括:
阅读手册here中的基础知识.
你的例子
这会在3integer
列之后产生4字节的填充,因为timestamp
列需要double
次对齐,并且需要从8字节的下一个倍数开始.
因此,一行占据:
23 -- heaptupleheader
+ 1 -- padding or NULL bitmap
+ 12 -- 3 * integer (no alignment padding here)
+ 4 -- padding after 3rd integer
+ 8 -- timestamp
+ 0 -- no padding since tuple ends at multiple of MAXALIGN
加上页面标题中每个元组的项标识符(如pointed out by @A.H. in the comment):
+ 4 -- item identifier in page header
------
= 52 bytes
所以我们得出了观察到的52 bytes.
计算pg_relation_size(tbl) / count(*)
是一个悲观的估计.pg_relation_size(tbl)
包括inflating (死行)和fillfactor
保留的空间,以及每个数据页和每个表的开销.(我们甚至没有提到对TOAST tables个长varlena
个数据的压缩,因为它不适用于这里.)
您可以安装附加模块pgstattuple,并致电SELECT * FROM pgstattuple('tbl_name');
以获取有关表和元组大小的更多信息.
相关的: