理解Postgres的行大小

我得到了一个大的(>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=intalignment(大多数机器上为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中的空间计算与节省

发表评论