PostgreSQLが貴重なHDスペースをすべて消費してしまうのはなぜですか?
-
03-07-2019 - |
質問
Wikipedia(英語)に関するリンク構造データをできるだけ多く転送し終えたところです。基本的に、ウィキペディアの最新のダンプリポジトリから多数のSQLダンプをダウンロードしました。私はMySQLの代わりにPostgreSQLを使用しているため、パイプラインシェルを使用してこれらすべてのダンプをdbにロードすることにしましたコマンド。
とにかく、これらのテーブルの1つには2億9,500万行があります。 pagelinks テーブル。すべてのウィキ内ハイパーリンクが含まれています。私のラップトップから、pgAdmin IIIを使用して、データベースサーバー(別のコンピューター)に次のコマンドを送信しました。
SELECT pl_namespace, COUNT(*) FROM pagelinks GROUP BY (pl_namespace);
もう1時間かそこらです。問題は、ポストマスターが私の非常に限られたHDスペースをますます使い果たしているように見えることです。今のところ約20 GBを消費したと思います。以前にpostgresql.confファイルをいじって、12 GBのRAMで実行するためにパフォーマンスの柔軟性を高めました(つまり、より多くのリソースを使用できるようにしました)。私は基本的に、このファイルのほとんどのバイトとそのような関連変数を4倍にしたと思います。
ただし、dbはそれほど多くのRAMを使用していないようです。 Linuxシステムモニターを使用すると、ポストマスターが1.6 GBの共有メモリ(RAM)を使用していることがわかります。とにかく、私はそれが何をしているのかをよりよく理解するのを助けることができるかどうか疑問に思っていました。
ウィキペディアのデータベースのメタ構造に関して、優れたスキーマ。有用な場合もあれば、興味がある場合もあります。
詳細についてはお気軽にお問い合わせください。
解決
問題を引き起こしているのはおそらくGROUP BYでしょう。グループ化を行うために、データベースは行をソートして重複するアイテムをまとめる必要があります。インデックスはおそらく役に立たないでしょう。封筒の裏側の計算:
各行に100バイトのスペース、つまり29,500,000,000バイト、または約30GBのストレージが必要だと仮定します。すべてをメモリに収めることができないため、システムがスラッシングし、操作が1000倍以上遅くなります。 HDスペースがスワップファイルを使用している場合、スワップスペースに消えている可能性があります。
この計算を1回だけ行う必要がある場合は、データの小さなサブセットに分割してみてください。 pl_namespaceが数値で範囲が1-295millionであると仮定して、次のようなものを試してください:
SELECT pl_namespace, COUNT(*)
FROM pagelinks
WHERE pl_namespace between 1 and 50000000
GROUP BY (pl_namespace);
その後、50000001-100000000などについても同様に行います。 UNIONを使用して回答を結合するか、外部プログラムで結果を単純に表にします。 GROUP BYに役立たないインデックスについて書いたことは忘れてください。ここでは、インデックスがWHERE句に役立ちます。
他のヒント
9.5MBのRAMしか消費していないと主張している正確には何ですか?共有メモリはほぼ間違いなく、異なるPostgresプロセス間で共有されているRAMである 。 (私が覚えていることから、各クライアントは別々のプロセスとして終了しますが、しばらくの間なので、非常に間違っている可能性があります。)
pl_namespace
列にインデックスがありますか?非常に多くの明確な結果がある場合、インデックスのない2億9,500万行のテーブルでクエリがかなり重いと想像できます。そうは言っても、10GBは飲み込むのが非常に困難です。書き込み先のファイルを知っていますか?
わかりましたので、ここにその要点があります:
GROUP BY句によってインデックスが無効になったため、ポストマスター(postgresqlサーバープロセス)は、ディレクトリ$ PGDATA / base / 16384 / pgsql_tmpにあるテーブルの束(23GBのテーブル)を作成することにしました。
postgresql.confファイルを変更するときに、postgreSQLに1.6 GBのRAMを使用する許可を与えました(11.7 GBのRAMにアクセスできるようになりました)。ポストマスタープロセスは実際に1.6 GBのRAMを使用していましたが、それだけでは十分ではなかったため、pgsql_tmpディレクトリです。
Barry Brownが指摘したように、このSQLコマンドを実行して pagelinks.namespaces 間のリンクの分布に関する統計情報を取得するだけだったので、 2億9,600万のページリンク(これは調査のために行うことです。)
コマンドが結果セットを返すと、何も起こらなかったようにすべての一時テーブルが自動的に削除されました。
ヘルプの皆さんへのThx!