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