web-dev-qa-db-ja.com

PostgreSQL:ディスク容量を節約するためにテーブルを分離するのか単一のテーブルにするのか?

同じ行数の以下のスキーマを持つ2つのテーブルがあります。 SELECT relname, relpages FROM pg_class ORDER BY relpages DESCコマンドを実行すると、2つのスキーマのデータ型(合計バイト数)のサイズが異なっていても、それぞれ23GBと表示されます。テーブルを組み合わせることでどれだけのスペースを節約できるかを把握するための最良の方法は何ですか?また、各行が実際にどのくらいのスペースを占めているかを判断する方法はありますか?

                                 Table "public.table1"
Column        |           Type           |                      Modifiers                      
--------------+--------------------------+-----------------------------------------------------

 field1       | smallint                 | 
 field2       | smallint                 | 
 field3       | integer                  | 
 field4       | smallint                 | 
 timestamp    | timestamp with time zone | 
 user_id      | integer                  | 
 status       | boolean                  | 
 id           | integer                  | not null default 

                                  Table "public.table2"
 Column          |           Type           |                     Modifiers                      
 ----------------+--------------------------+----------------------------------------------------
 user_id         | integer                  | 
 begin_timestamp | timestamp with time zone | 
 end_timestamp   | timestamp with time zone | 
 field           | smallint                 | not null
 id              | integer                  | not null default 
3
Chirag Patel

これに対する合理的な答えは、私見が質問をする(または少なくとも暗示する)必要があります:なぜ最初にテーブルが分割されたのですか? (さらに重要なこと:それはまだ適用されますか?)

一般的なケース: postgres dbエンジンの動作の詳細はわかりませんが、保存されたディスク領域の下限は、削除された列のサイズ+重複変数のインデックス+以下である可能性があります。ハウスキーピングデータのビット

上限もかなり小さいので、おそらく問題の価値はないでしょう。一部の列はより頻繁にアクセス(読み取り、または更新)されるため、パフォーマンス上の理由でパーティション化されている可能性もあります。そのため、列を小さく(列を少なく)して高速化することができます。 (両方から同時に列にアクセスすると、いくらかのペナルティがあります。)

特定のケース:それらの間に冗長なフィールドがたくさんあるようです。たとえば、user_idは2回存在する必要はありません。 begin/end/Xタイムスタンプは、おそらく2つまたは1つに減らすことができます。したがって、アプリケーションの要件によっては、そこからわずかに節約できる可能性があります。繰り返しになりますが、そもそもなぜ彼らがそれをしたのかを理解してみてください。

しかし、全体として、私はブライアン・エイジに同意します。そもそもpostgresを実行するのに十分な大きさのものについては、ディスク容量を気にする必要はないでしょう。特に、これを「修正」するために費やした時間に対して支払いを受ける場合、そのコストは、より大きなディスク自体のコストを超える可能性があります。

行ごとのスペース:私はpostgresの詳細に精通していないので、知識のある人は何か間違ったことを修正できるはずです。その特定の行が実際にどのくらいのスペースを占めているかをpostgresに尋ねる方法があるなど。何も知りません。私が書いているのは、基本的に、今日一般的に行われている(私が信じている)データベースストレージの背後にある理論です。

各フィールドには、値がnullであるかどうかを示すビット(独自のバイト、または行全体に共通のビットセット)があります。 null値の場合、これ以上保存されるものはありません。次に、長さバイトがあります-これが固定幅のデータ型から暗黙的でない限り。次に、データ自体があります。

したがって、1つのint(64ビットでも)と3つのnull値の行は、わずか3バイトしかかかりません。 (値<127の場合、size = 1とバイトを格納します。)プラスインデックス、およびその他のさまざまなハウスキーピングメタデータ。繰り返しになりますが、この点でpostgresがどこまで進んでいるかはわかりません。そして、これらの要素をすべて組み合わせると、「この行がどれだけ占有するか」という質問が役に立たない答えになる傾向があります。

AFAIK postgresは、「ページ」(行が境界を越えて格納されない可能性のあるスペースのブロック)でも動作します。そのため、大きなレコードはページに「収まらない」場合が多く、別の/新しいページに配置する必要があります。

1
MaHuJa

結果として得られる結合テーブルには、それぞれのテーブルのレコードに未使用の行が含まれるため、スペースを獲得できず、失う可能性があります。

それよりも重要なのは、ディスク容量の理由から、その性質のアーキテクチャを決定することを強くお勧めしません。ディスクは安価です。適切に設計された機能的なアプリケーションはそうではありません。実行時のパフォーマンスに問題がある場合(つまり、46 GBすべてがメモリ/スワップスペースにロードされている場合)、最適化と調整の問題が発生している可能性があります。

3
Bryan Agee