我得到了一个大的(>100M行)Postgres表,其结构为{integer,integer,integer,timestamp without time zone}。我希望行的大小为3*integer+1*timestamp=3*4+1*8=20字节
实际上,行大小是pg\u关系\u大小(tbl)/count(*)
=52字节。为什么?
(未对表执行任何删除:pg\u relation\u size(tbl,'fsm')
~=0)
行大小的计算要复杂得多
存储通常以8KB数据页进行分区。每页有一个小的固定开销,可能的余数不足以容纳另一个元组,更重要的是死行或最初使用FILLFACTOR
设置保留的百分比
而且每行(元组)的开销更大:页面开头的项标识符为4个字节,HeapTupleHeader
为23个字节,对齐填充为。元组头的开头和元组数据的开头以maxallign
的倍数对齐,在典型的64位机器上为8字节。某些数据类型需要对齐到下一个2、4或8字节的倍数
引用系统表上的手册pg_tpye
:
typallign
是存储此类型的值时所需的对齐方式。
它适用于磁盘上的存储以及
PostgreSQL中的值。当存储多个值时
连续地,如在一个完整的行的表示中
磁盘,填充在该类型的基准之前插入,以便
从指定的边界开始。路线参考是
序列中第一个基准的起点可能的值为:
c
=char
对齐,即不需要对齐
s
=short
对齐(大多数机器上为2字节)
i
=int
alignment(大多数机器上为4字节)
d
=double
对齐(许多机器上有8个字节,但决不是全部)
请在此处阅读手册中的基础知识
你的榜样
这将导致在3个整数
列之后有4个字节的填充,因为时间戳
列需要双
对齐,并且需要从下一个8字节的倍数开始
因此,一行占用:
23--heaptupleheader
+1—填充或空位图
+12--3*整数(此处无对齐填充)
+4—第三个整数后的填充
+8——时间戳
+0--没有填充,因为元组以MAXALIGN的倍数结尾
加上页面标题中每个元组的项标识符(正如@A.H.在注释中指出的):
+4--页眉中的项目标识符
------
=52字节
因此,我们得到了观察到的52个字节
计算pg\u关系\u大小(tbl)/count(*)
是一个悲观的估计pg\u关系\u大小(tbl)
包括膨胀(死行)和fillfactor
保留的空间,以及每个数据页和每个表的开销。(我们甚至没有提到TOAST表中longvarlena
数据的压缩,因为它在这里不适用。)
您可以安装附加模块pgstattuple并从pgstattuple调用SELECT*('tbl_name')
相关的:
- 表格大小与页面布局
- PostgreSQL中的空间计算与节省