27

7 つの列を持つテーブルがあり、そのうちの 5 つが null になります。、、、、およびデータ型intにnull 列があります。このテーブルには、多数のヌルを含む何百万もの行が含まれます。null 値がスペースを占有するのではないかと心配しています。textdatebooleanmoney

また、Postgres が null 値にインデックスを付けているかどうか知っていますか? nullのインデックスを作成しないようにしたいと思います。

4

3 に答える 3

49

基本的に、値は NULL ビットマップの1 ビットNULLを占めます。しかし、それはそれほど単純ではありません。

null ビットマップ(行ごと) は、その行の少なくとも 1 つの列がNULL値を保持している場合にのみ割り当てられます。これは、9 つ​​以上の列を持つテーブルで一見逆説的な効果につながる可能性があります。最初のNULL値を列に割り当てると、値を書き込むよりもディスク上のスペースが多くなる可能性があります。逆に、行から最後の NULL 値を削除すると、NULL ビットマップも削除されます。

物理的には、最初の null ビットマップは(23 バイト) と実際の列データまたは行(まだ使用している場合)の間の1 バイトを占めます。これは常に(通常は8 バイト)の倍数から始まります。これにより、最初のヌル ビットマップで使用される1 バイトのパディングが残ります。HeapTupleHeaderOIDMAXALIGN

実際には、NULL ストレージは、8 列以下のテーブル(ドロップされたがまだパージされていない列を含む) に対して完全に無料です。
その後、別のバイト (通常は 8) が次の列 (通常は 64)MAXALIGNに割り当てられます。MAXALIGN * 8等。

詳細については、マニュアルおよび関連する質問を参照してください。

データ型のアラインメント パディングを理解したら、ストレージをさらに最適化できます。

ただし、かなりの量のスペースを節約できるケースはまれです。通常、努力する価値はありません。

@ダニエルはすでにインデックスサイズへの影響をカバーしています。

削除された列(現在は表示されていません) は、テーブルが再作成されるまでシステム カタログに保持されることに注意してください。これらのゾンビは、(拡大された) NULL ビットマップの割り当てを強制できます。見る:

于 2012-08-27T18:04:53.007 に答える
14

値がインデックスに到達するかどうかNULLは、少なくともインデックスのタイプに依存します。基本的に、これはインデックスタイプの場合はYES、インデックスタイプの場合はNObtreeなり、PostgreSQLのバージョンに応じてインデックスタイプの場合はYESまたはNOのように見えます。gisthashgin

以前はその情報を保持するブール列amindexnullspg_catalog.pg_amテーブルにありましたが、9.1ではなくなりました。おそらく、PGの改善の中でインデックスがさらに洗練されたためです。

pg_relation_size('index_name')データの特定のケースでは、関数を使用して、完全にNULLと完全にNOT NULLのコンテンツ間で、正確なPGバージョン、正確なデータ型、正確なインデックスタイプ、および定義を使用して、インデックスのサイズの違いを測定するのが最善の方法です。。そして、おそらく、これらのパラメータのいずれかが将来変更されると、結果が変わる可能性があることを知っておいてください。

ただし、いずれの場合でも、NULLのインデックス作成を「単に」避けたい場合は、部分インデックスを作成することが常に可能です。

CREATE INDEX partial_idx(col) ON table WHERE (col is not null)

これにより必要なスペースは少なくなりますが、これがクエリのパフォーマンスに役立つかどうかは、これらのクエリに依存します。

于 2012-08-27T17:16:08.630 に答える
2

それぞれが行のビットマップで単一のビットを使用すると思います。ここを参照してください: http://www.postgresql.org/docs/9.0/static/storage-page-layout.html#HEAPTUPLEHEADERDATA-TABLE

于 2012-08-27T16:31:13.073 に答える