web-dev-qa-db-ja.com

PostgreSQLデータファイルのサイズはデータ自体よりも大きい

PostgreSQL DBにデータをアーカイブするシステムがあります。 DBアーカイブのために、PCストレージがいっぱいであることがわかりました。問題は、/var/lib/pgsql/data/base/にあるデータファイルをチェックしたところ、合計で約70 GBでしたが、pg_dumpを使用してすべてのデータベースをダンプすると、出力ファイルが24 GBを超えませんでした。私はここで何かを逃したり、何かを誤解したりしていますか?このサイズの大きな違いはどこに行きますか?

編集:スキーマとデータを含めるためにpg_dumpを実行し、ドロップと作成を許可するオプション-cを指定しました。

編集2:DBスキーマファイルを調査したところ、24 GB(約332.4ミリオンの行)のデータのうちほぼ23.9 GBを含むテーブルにインデックスが付いていることがわかりました。別のテーブルに別のインデックスがありますが、テーブルが空です。

編集3:プログラムは約1500の変数の値を定期的に保存します。つまり、すべての変数は0.1秒から1分またはそれ以上記録されているため、ここに巨大なDBアクセスがあると思います。

編集4:2番目のクエリ here を実行して、スキーマ内の各リレーションのサイズを調べ、次のことを確認しました。

  • メインデータテーブル用に28 GB。
  • 3つのインデックスのみで約42 GB! 24、9、9。

私の目的は、頻繁に(数か月ごとに)バックアップと復元を行うことです。バックアップと復元を行うときにこれらのDBインデックスを気にする必要がありますか、それともデータテーブルにのみ焦点を当てるべきですか?

7
3bdalla

サイズはいくつかの理由により異なる場合があります:

  • インデックスはいくらかのディスク容量を必要とし、
  • ディスク上に同じレコードの複数のコピーが存在する可能性があります。
  • ページ内のスラックスペース。

インデックスは、より高速な検索を容易にするために、ディスク領域を占有します。インデックスが多いほど、DBが使用するディスク領域が多くなります。通常、GINインデックスは小さくなりますが、範囲クエリを使用する場合は役に立ちません。

PostgreSQLは、レコードの更新と削除がレコードの可視性を変更するだけで、実際にはデータを削除または上書きしないように実装されている同時アクセスをサポートしています。更新すると、新しい(更新された)コピーが追加されます。どちらも古いデータがまだディスクに書き込まれていることを意味します。それを解放するために、PostgreSQLは定期的にバキューム処理を実行し、削除されたレコードを本当に削除します(トランザクションがそれらを使用していない後)。

PostgreSQLのデフォルトのブロックサイズは8KBです。レコードが大きい、たとえば5KBの場合、1ブロックで1つのレコードしか取得できず、かなり大きな(3KBまで)スラックがあります。

考えられる解決策は次のとおりです。

  • PostgreSQLのディスク使用状況を確認する方法を確認してください
  • すべてのインデックスが本当に必要かどうかを再評価し、
  • データアクセスパターンが何であるかを考えてください。それがテーブルのみを追加する場合、目に見えないレコードはほとんどないはずです。一方、データが一時的に変更され、一定期間後にアーカイブされる場合は、複数のレコードがディスク上にあると見積もることができます。この場合は、パーティションを個別にバキュームできるため、テーブルのパーティション分割が役立つ場合があります。
  • テーブルを手動でバキュームできます 。 VACUUM FULLはテーブルの新しいコピーを書き込み、適切な量のディスク容量を必要とするため、使用しないでください。
  • pg_repack などのオンライン(DBをシャットダウンする必要がないようにオンライン)再梱包ツールを使用できます。

編集:

pg_dump

pg_dumpは、あなたが言ったように、データをダンプするように指定した場合は問題ありません。カスタムフォーマット(-Fcフラグ)を使用する場合、pg_restoreはそれを使用して、指定されたテーブルのみをロードするなどの追加の処理を実行できます。pg_dumpのマニュアルページも参照してください。カスタム形式のgzipはデフォルトでダンプします。これにより、ダンプが遅くなる可能性があるため、これを無効にすることができます。データをgzip圧縮したい場合は、並列gzip(pigz)を使用できます。

バックアップ

バックアップするときは、テーブル内のデータをバックアップします。インデックスはテーブル内のデータから再作成されます。バックアップとリストアを実行するときにデータベースに重いIOを割り当てる余裕がある場合は、pg_dumpとpg_restoreがニーズに合う場合があります。ダンプ時には、pg_dumpはテーブルのみをダンプし、リストア時には、リストアの一部としてインデックスが自動的に再構築されます。明確にするために、バックアップはインデックスを気にしません。

重いIOでパフォーマンスの低下が許容できない場合は、セカンダリレプリケーションサーバーを用意することをお勧めします。セカンダリレプリケーションサーバーには、データのコピーはありますが、通常のクエリは提供されないため、次のように使用できます。捨てる。

特定時点の復元機能が必要な場合は、WALログ(先読みログ)アーカイブをセットアップできます。これにより、特定のトランザクションに復元できますが、これはかなり高度です。 Barman などの役立つツールがあります。

大きなインデックス

すでに発見したように、インデックスは多くのスペースを占有する可能性があります。データとインデックスを合計すると、DBサイズは28GB + 42GB = 70GBになります。

インデックスが大きいということは、多くの余分なディスク領域が使用されることを意味します。インデックスデータもメモリにキャッシュされるため、大きなインデックスがあると、RAMにインデックスデータのコピーが2つ存在する可能性があります。つまり、ディスク上のデータをキャッシュするためのRAMが少なくなり、キャッシュミスが多くなります。インデックスを小さくするために評価するいくつかのオプションがあります。

  • 部分インデックス:1つのフィールドが特定の値に設定されている場所でのみアプリケーションがクエリを実行する場合、CREATEのWHERE句を使用してインデックスを作成する行を制限できますINDEX。
  • インデックススキャンを使用する:クエリされたすべてのデータをインデックスに含めることができる場合、PostgreSQLはインデックスデータのみを読み取ることによって返すことができます。 PostgreSQL 9.2以降で動作します。wikiの インデックススキャンの詳細を参照してください
  • 別のタイプのインデックスを使用する:アプリケーションが等式ルックアップのみを行う場合(WHERE a = 4)、GINインデックスははるかに小さくなる可能性があります。 を参照してくださいbtree_gin拡張 。 PostgreSQL 9.5はBRINインデックスも提供します。これは、タイムスタンプなどの単調な増加または減少のパターンがあり、非常に小さいフィールドに非常に役立つため、ディスク領域を解放してより多くのストレージとRAMより多くのデータをキャッシュします。

しかし...これの多くは、データへのアクセス方法に依存します。これは多くの場合、アプリケーションの開発者だけが知っています。

12
hruske

pg_dumpには、データベースの再作成に必要なSQLステートメントのみが含まれています。

実際のデータファイルには、挿入したデータと他のすべてのデータベースオブジェクト、特にインデックスが含まれます。クラスター化インデックス(データ自体)と非クラスター化インデックス:指定したキーで並べ替えられた選択した列。

Pd_dumpにはCREATE INDEXステートメントが含まれ、データファイルにはインデックス自体が含まれます(非常に大きい場合があります)。

3
BuahahaXD