web-dev-qa-db-ja.com

テーブル行ごとにディスク上のスペースを決定または予測する方法は?

私はPostgresに非常に慣れていないので、私の数学はここから外れる...

これは私のテーブルです:

CREATE TABLE audit (
    id BIGSERIAL PRIMARY KEY,
    content_id VARCHAR (50) NULL, 
    type VARCHAR (100) NOT NULL, 
    size bigint NOT NULL, 
    timestamp1 timestamp NOT NULL DEFAULT NOW(), 
    timestamp2 timestamp NOT NULL DEFAULT NOW()
);

1行が占めるスペースを見積もりたいのですが。いくつか読んだ後、私はこれを思いつきました、それは正しいですか?

1 row =
23 (heaptupleheader)
+ 1 (padding)
+ 8 (id)
+ 50 (content_id)
+ 6 (padding)
+ 100 (type)
+ 4 (padding)
+ 8 (size)
+ 8 (timestamp)
+ 8 (timestamp)
= 216 bytes

ローカルのPostgres DBにも同じテーブルを作成しましたが、数値が一致していないようです。

INSERT INTO public.audit(content_id, type, size)
    VALUES ('aaa', 'bbb', 100);

SELECT pg_size_pretty( pg_total_relation_size('audit') );  -- returns 24 kb

INSERT INTO public.audit(content_id, type, size)
    VALUES ('aaaaaaaaaaaaa', 'bbbbbbbbbbbbbb', 100000000000);

SELECT pg_size_pretty( pg_total_relation_size('audit') ); -- still returns 24 kb

Postgresは24 kbのスペースを最初から予約していると思いますが、24 kbを超えると、より多くのデータを入力すると、132バイトずつ増加しますか?しかし、私の中で何かが正しくないことを言います。

Postgres dbで1行が占めるスペースを確認したいので、そこに格納できるデータ量を分析できます。多分私は非常に明白な何かを見逃している。

2
90abyss

計算は、裸の最大行サイズに近いです。実際の範囲は、行あたり68〜212バイト、またはインデックスを含めて84〜228バイトです。

最も重要なのは、varchar(n)が最大長を占める必要がないことです。データ型はvarlenaで内部的に実装されます。これにより、ディスク上の短い文字列に1バイトのオーバーヘッドと、文字列の実際のバイト数が追加されます。

varlenaを使用して実装されたデータ型は、ディスク上に配置パディングを必要としません。

そしてNULL値(content_id)は事実上無料です。見る:

最後にPRIMARY KEY制約は、標準のbtreeインデックスを使用して実装されます。これをディスクの合計サイズに追加する必要があります。

したがって、ディスク上の行サイズの計算は次のとおりです。

 23バイトのタプルヘッダー
 1バイトのパディングまたはnullビットマップ
 8バイトのID BIGSERIAL PRIMARY KEY 
 0〜51バイトのcontent_id VARCHAR(50)NULL 
 0バイトアラインメントパディング
 2〜101バイトタイプVARCHAR(100)NOT NULL 
?バイトアラインメントパディング
 8バイトサイズbigint NOT NULL 
 8バイトtimestamp1タイムスタンプNOT NULL 
 8バイトtimestamp2タイムスタンプNOT NULL 
 --- 
分64(6バイトのパディングを含む)-最大208バイト(パディングは不要)
 
 +ヒープページの4バイトのアイテム識別子
 --- 
 68-212バイト
 
 +インデックスタプル用16バイト
 --- 
 84-228バイト

さらに、次の関連する質問で詳しく説明されているように、ヒープページとインデックスページのオーバーヘッドがいくつかあります。

ディスク上の実際の行サイズ(アイテムIDなし):

SELECT pg_column_size(a) AS size_on_disk, *
FROM   audit a;

RAMのサイズは異なる場合があります:

SELECT pg_column_size(content_id) AS content_id_size_on_disk
     , pg_column_size(content_id || '') AS content_id_size_in_ram
     , content_id
FROM   audit a;

見る:


約 ...

Postgresは開始するために24 kbのスペースを予約していると思います

ヒープは0バイトから始まります。インデックスは1つのメタページ(8kb)で始まります。最初の行を追加すると、最初のヒープページに最低8 kb、インデックス(最低1メタページ+最初のインデックスページ)に16 kbが表示されます。フィドルの詳細!

db <> fiddle ここ

2

PostgreSQLのドキュメント と次の StackOverflowの質問/回答 が出発点として適しています。

0
armitage