web-dev-qa-db-ja.com

大きなテーブルの完全に空の列はパフォーマンスにどのように影響しますか?

Postgres dbに4億行あり、テーブルには18列あります。

id serial NOT NULL,
a integer,
b integer,
c integer,
d smallint,
e timestamp without time zone,
f smallint,
g timestamp without time zone,
h integer,
i timestamp without time zone,
j integer,
k character varying(32),
l integer,
m smallint,
n smallint,
o character varying(36),
p character varying(100),
q character varying(100)

ek、およびnはすべてNULLであり、値をまったく格納せず、この時点では完全に役に立たない。それらは元のデザインの一部でしたが、削除されませんでした。

編集-他の列のほとんどはNULL以外です。

質問:

  1. これがストレージに与える影響を計算するにはどうすればよいですか?列のサイズ*行の数に等しいですか?

  2. これらの空の列を削除すると、このテーブルのパフォーマンスが著しく向上しますか?ページキャッシュはより多くの行に対応できますか?

8
ebi

ek、およびnはNULLになる可能性があるため、「100%空」はNULLを意味すると想定しています。

NULLストレージは安価です。各NULLは、ストレージのnullビットマップの1ビットを「消費」し、それ以外の場合はパフォーマンスにほとんど影響しません。有効なストレージ要件は、各行のnullビットマップがすでに存在していて、さらに3ビット分のスペースがあるかどうかによって異なります。

8列までのテーブルでは、nullビットマップのタプルヘッダーの後にスペアバイトを利用できます。その後、別のMAXALIGN(通常8バイト)が割り当てられ、別の64列(合計72現在)。したがって、nullビットマップは、18列を持つyoursを含むほとんどのテーブルで、1行あたり8バイトのコストがかかります。

Nullビットマップは、行ごとに完全に割り当てられるか、まったく割り当てられません。ただし、実際のNULL値が少なくとも1つある場合のみ。すべての列が定義されている場合NOT NULL、存在することはありません。

他のより重要な考慮事項がない場合は、常に(またはほとんど)NULLである列を行の最後に移動します。パフォーマンスを少しだけ向上させます。

1の答え。

有効なストレージ要件は次のとおりです。

  • 他の列もNULLである行ごとに0バイト
  • 8バイト(通常)他の列がNULLでない行ごとに、nullビットマップを割り当てるため

2.への回答。

落としてもあまり買わない。ページキャッシュは、1に応じて同じかわずかに少なくなります。クエリ、バックアップ、ソースコードなどの処理が簡略化されます。

詳しくは:

あなたが求めなかったもの

「列テトリス」のラウンドの後、このテーブルレイアウトを提案します。ここでも、他のより重要な考慮事項を除きます。

id serial NOT NULL,
a integer,
b integer,
c integer,
g timestamp,
i timestamp,
d smallint,
f smallint,
h integer,
j integer,
l integer,
m smallint,
o character varying(36),
p character varying(100),
q character varying(100),
e timestamp,              --  always NULL
k character varying(32),  --  always NULL
n smallint                --  always NULL

varchar列にもよりますが、元のレイアウトと比較して、行あたり少なくとも16バイト、おそらく約20バイト以上節約できます。 「列テトリス」の説明はこちら:

列を並べ替える方法

simplestメソッドは、新しいテーブルを作成し、そこにデータをコピーします。次に、無効な列(および無効な行)のない手付かずの新しいテーブルを取得します。プロセス内の行の物理的な順序もソート(クラスター)できます。

場所の変更も可能ですが、一般的に列の順序を並べ替える便利なツールはありません(私は知っています)。ここでは、ビュー、関数(依存)、FK制約、インデックスなどの依存オブジェクトが制限要因となります。これらは列の削除を妨げる可能性があるため、依存するオブジェクトを削除して再作成する必要があります。

そしてもちろん、テーブルへの同時アクセスは、それを変更するDDLコマンドと競合します。この場合、排他ロックが必要です。

完全に空の列を削除して、行の最後に追加するのは簡単で安価です。テーブルの中央にあるデータが設定された列の順序を切り替えることはそれほど簡単ではありません。そのための新しいテーブルを作成します。

この関連する回答には、レシピと詳細へのリンクがあります。

12