行サイズの計算は、それよりもはるかに複雑です。
通常、ストレージは 8 kB のデータ ページに分割されます。ページごとに小さな固定オーバーヘッドがあり、残りが別のタプルに収まるほど大きくない可能性があり、さらに重要なことに、デッド行またはFILLFACTOR
設定で最初に予約されたパーセンテージがあります。
また、行(タプル)ごとにさらに多くのオーバーヘッドがあります。ページの先頭にある 4 バイトの項目識別子HeapTupleHeader
、23 バイトの 、および配置パディングです。タプル ヘッダーの開始とタプル データの開始は、 の倍数 (MAXALIGN
一般的な 64 ビット マシンでは 8 バイト) で配置されます。一部のデータ型では、次の 2、4、または 8 バイトの倍数に位置合わせする必要があります。
システムテーブルのマニュアルを引用pg_tpye
:
typalign
この型の値を格納するときに必要な配置です。これは、ディスク上のストレージだけでなく、PostgreSQL 内の値のほとんどの表現にも適用されます。ディスク上の完全な行の表現など、複数の値が連続して格納される場合、指定された境界で始まるように、このタイプのデータムの前にパディングが挿入されます。位置合わせ参照は、シーケンス内の最初のデータムの始まりです。
可能な値は次のとおりです。
c
=char
整列、つまり、整列は必要ありません。
s
=short
整列 (ほとんどのマシンでは 2 バイト)。
i
=int
整列 (ほとんどのマシンでは 4 バイト)。
d
=double
アライメント (多くのマシンでは 8 バイトですが、すべてではありません)。
マニュアルの基本については、こちらをご覧ください。
あなたの例
integer
これにより、3列の後に 4 バイトのパディングが発生します。これは、timestamp
列にはdouble
位置合わせが必要であり、次の 8 バイトの倍数から開始する必要があるためです。
したがって、1 行が占めます。
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
さらに、ページ ヘッダーのタプルごとのアイテム識別子 (コメントで @AH が指摘したように):
+ 4 -- item identifier in page header
------
= 52 bytes
したがって、観測された52 バイトに到達します。
計算pg_relation_size(tbl) / count(*)
は悲観的な見積もりです。pg_relation_size(tbl)
膨張 (無駄な行) と によって予約されたスペースfillfactor
、およびデータ ページごとおよびテーブルごとのオーバーヘッドが含まれます。(また、 TOAST テーブルvarlena
の長いデータの圧縮については触れていません。ここでは適用されないためです。)
追加のモジュールpgstattupleSELECT * FROM pgstattuple('tbl_name');
をインストールして、テーブルとタプルのサイズに関する詳細情報を呼び出すことができます。
関連している: