varchar(n)のオーバーヘッドは何ですか?


15

型に関するPostgres docからこのフラグメントの意味を尋ねたいと思いましたvarchar(n)

短い文字列(最大126バイト)のストレージ要件は、1バイトに実際の文字列を加えたもので、文字の場合はスペースの埋め込みが含まれます。長い文字列には、1ではなく4バイトのオーバーヘッドがあります。

私にはvarchar(255)フィールドがあると仮定しましょう。そして今、次のステートメント:

  • このフィールドが10バイトの文字列を保持する場合、オーバーヘッドは1バイトです。したがって、文字列は11バイトを使用します。
  • フィールドに140バイトを使用した文字列が含まれている場合、オーバーヘッドは4バイトです。したがって、文字列は144バイトを使用します。

上記のステートメントは真実ですか?ここで誰かが私と同じようにドキュメントを理解していますが、ここでは誰かがオーバーヘッドが常に4バイトであると述べていますか?

回答:


19

当然、マニュアルは正しいです。しかし、それだけではありません。

1つは、ディスク上のサイズ(実際にはディスクに格納されていない場合でも、テーブル内)がメモリ内のサイズと異なる場合があります。ディスクでは、マニュアルに記載されているように、varchar126バイトまでの短い値のオーバーヘッドが1バイトに削減されます。ただし、メモリのオーバーヘッドは常に4バイトです(個々の値が抽出されると)。

同じことが当てはまりますtextvarcharvarchar(n)またはchar(n)その以外- char(n)空白埋めにあるn文字、あなたが正常にそれを使用する必要はありません。その有効サイズnは、バイトではなく最大文字数を示すため、マルチバイトエンコーディングでも変わります。

までの文字列のn長さの文字(バイトではありません)。

それらはすべてvarlena内部で使用します。
"char"(二重引用符付き)は別のクリーチャーであり、常に1バイトを占有します。
型指定されていない文字列リテラル'foo')には、1バイトのオーバーヘッドがあります。型付きの値と混同しないでください!

でテストしpg_column_size()ます。

CREATE TEMP TABLE t (id int, v_small varchar, v_big varchar);
INSERT INTO t VALUES (1, 'foo', '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890');

SELECT pg_column_size(id)        AS id
     , pg_column_size(v_small)   AS v_small
     , pg_column_size(v_big)     AS v_big
     , pg_column_size(t)         AS t
FROM   t
UNION ALL  -- 2nd row measuring values in RAM
SELECT pg_column_size(1)
     , pg_column_size('foo'::varchar)
     , pg_column_size('12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'::varchar)
     , pg_column_size(ROW(1, 'foo'::varchar, '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890'::varchar));

 id | v_small | v_big |  t
----+---------+-------+-----
  4 |       4 |   144 | 176
  4 |       7 |   144 | 176

ご覧のように:

  • 3バイトの文字列「foo」は、ディスクで4 バイト、RAMで7バイトを占有します(1バイト対4バイトのオーバーヘッド)。
  • 140バイトの文字列「123 ...」は、ディスクとRAMの両方で144バイトを占有します(常に4バイトのオーバーヘッド)。
  • のストレージにintegerはオーバーヘッドがありません(ただし、パディングを課す可能性があるアライメント要件があります)。
  • 行には、タプルヘッダー用に24バイトの追加オーバーヘッドがあります(さらに、ページヘッダー内のアイテムポインター用にタプルごとに4バイトが追加されます)。
  • そして最後になりましたがvarchar、行のサイズからわかるように、小のオーバーヘッドは行から抽出されていませんが、まだ1バイトだけです。(そのため、行全体を選択する方が少し速い場合があります。)

関連:


1
その1バイトのオーバーヘッドはまだインデックスの1バイトですか?
dvtan

1
@dtgq:インデックスはテーブルのようにデータを保存するため、はい。
アーウィンブランドステッター
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.