web-dev-qa-db-ja.com

なぜ私のデータベースは挿入されたデータより12倍大きいのですか?

データベースサイズについて短い質問があります。データベースにデータを挿入する必要があります。挿入する前に、いくつかの計算を行う必要があります。

重要なのは、50 mbのプレーンデータ(約700,000行)から、結果として600 mbのdbサイズになるということです。これは係数12です。私はここで何か間違ったことをしていると確信しています。私のデータベースのサイズを再計算するのを手伝ってくれませんか?データベースサイズのソースは、web postgres管理インターフェイスです。

これが挿入です:

CREATE TYPE CUSTOMER_TYPE AS ENUM
('enum1', 'enum2', 'enum3', '...', 'enum15');       ## max lenght of enum names ~15

CREATE TABLE CUSTOMER(
   CUSTOMER_ONE    TEXT PRIMARY KEY NOT NULL,       ## max 35 char String
   ATTRIBUTE_ONE   TEXT UNIQUE,                     ## max 35 char String
   ATTRIBUTE_TWO   TEXT UNIQUE,                     ## max 51 char String
   ATTRIBUTE_THREE TEXT UNIQUE,                     ## max 52 char String
   ATTRIBUTE_FOUR  TEXT UNIQUE,                     ## max 64 char String
   ATTRIBUTE_FIFE  TEXT UNIQUE,                     ## 1-80 char String
   CUSTOMER_TYPE   PRIVATEKEYTYPE                   ## see enum
);

私はそれがなくても挿入できるので、私は本当にその列挙を必要としません。列挙型はデータベースサイズに影響しますか?

サイズを小さくする方法はありますか? (x12の代わりに)係数x4に到達することは可能ですか?そうでない場合は、必要に応じて一部の列を削除できます。

たぶん、文字データ用に他のPostgresデータ型があるのでしょうか?

ここでフィードバックした後、更新されたテーブルは次のようになります。

CREATE TABLE CUSTOMER(
   CUSTOMER_ONE    TEXT PRIMARY KEY NOT NULL,       ## max 35 char String
   ATTRIBUTE_ONE   TEXT UNIQUE,                     ## max 35 char String
   ATTRIBUTE_TWO   TEXT,                            ## max 51 char String
   ATTRIBUTE_THREE TEXT,                            ## max 52 char String
   ATTRIBUTE_FOUR  TEXT,                            ## max 64 char String
   ATTRIBUTE_FIFE  TEXT,                            ## 1-80 char String
   CUSTOMER_TYPE   PRIVATEKEYTYPE                   ## see enum
);

以前:12x

今:7x :)

他に可能な最適化はありますか? (列の削除を除きますか?)他のデータ型がより少ないスペースを使用しているのでしょうか?

3
A.c

text はプレーンテキストに最適なタイプです。内部的にはテキスト値だけでもほぼ同じです(もちろんエンコードの詳細にも依存します:UTF-8?)。あなたのケースではフィールドあたり1バイトの小さなオーバーヘッド。見る:

enum 列は合計サイズにほとんど貢献しません。行ごとに4バイト(内部ではreal数量)。列挙名の長さは実質的に無関係であり、データ型nameとして1回として保存されるため、最大NAMEDATALEN (通常63文字)。型宣言のための最小限のオーバーヘッド。したがって、enum列は実際にはテキストファイル内よりもDB内でlessスペースを占有します。
Postgresストレージにはさまざまなタイプのオーバーヘッドがありますが、それはであることを示しています。それらの一部には、1回限りのコスト、行数または関係などの他のスケールがあります。カタログテーブル(システムデータ)、インデックス、関係、テーブル統計、簿記データなどがあります。

サイズが12倍で、50 MBの生テキストデータの平均よりも大きいようです。しかし、それは本当に詳細に依存します。多くの小さな行には多くのオーバーヘッドがあり、少数の大きな行はそれほど多くなく、圧縮してさらに小さくすることもできます。 a_horseはすでに主な理由を指摘していました:6つのインデックス-一部は明らかに不必要です。

テーブルの各行には、23バイトを占めるタプルヘッダーがあり(さらに、アラインメントパディング、通常は24バイト)、列とタプル間のアラインメントパディング、アイテムポインター用に4バイト、データページあたりのオーバーヘッド(通常は8kbページサイズ)があります。あなたの場合、行あたり約35バイト。

すべてのインデックスタプルとほぼ同じです(ヘッダーには8バイトしかありませんが、インデックスは膨らみます)。 6つのインデックス、テーブル行ごとに〜150バイト最小。さらに、すべてのテキスト列が2回、1xテーブル、1xインデックスで保存されます。また、btreeインデックスはFILLFACTORが90で始まるため、すべてに対して+ + 10%です。

平均行サイズは〜75バイトです(50MB/700000-「行」が行に対応すると想定)。テーブルとインデックスは、生のテキストの約6倍のサイズを占めます。残りは上記のその他のオーバーヘッドです。

(まだ)テーブルの膨張がないことを前提としています。 DBを操作すると(更新、削除、トランザクションのロールバックなど)、デッド行などが発生し、合計スペースが増加する可能性があります。それは書き込みパターンに大きく依存します。

不要なインデックスを削除することで、大幅に節約できます。

enum列をテーブルの上部に移動すると、行あたり数バイト:整列パディングが少なく、行あたり平均1.5バイト、合計で約1 MBになるため、ほとんど価値がありません。見る:

5