4

私は、70GB 相当の xml ドキュメントから多数の情報を取得し、それをリレーショナル データベース (この場合は postgres) にロードしようとするプロジェクトの最中です。現在、python スクリプトと psycopg2 を使用して、この挿入などを行っています。 . 一部のテーブルの行数が増えると、それがわかりました。(そのうちの最大のものは約 500 万行です) スクリプト (挿入) の速度が遅くなりました。以前は数分かかっていた作業が、今では約 1 時間かかります。

これをスピードアップするにはどうすればよいですか? このタスクに python と psycopg2 を使用するのは間違っていましたか? このプロセスを高速化するためにデータベースに対してできることはありますか? 私はこれについて完全に間違った方法で行っていると感じています。

4

7 に答える 7

2

プロセスが以前はかなり効率的だったことを考えると、データセットが大きくなったときだけ、それは遅くなりました。私の推測では、それはインデックスです。インポートの前にテーブルにインデックスを削除し、インポートが完了した後にインデックスを再作成してみてください。それは物事をスピードアップするはずです。

于 2011-02-11T12:39:49.537 に答える
1

wal_buffersとcheckpoint_segmentsの設定は何ですか?大規模なトランザクションの場合、いくつかの設定を微調整する必要があります。マニュアルを確認してください。

PostgreSQL 9.0 High Performanceの本も検討してください。高性能を得るには、データベース構成だけでなく、さらに多くの調整が必要です。

于 2011-02-11T12:27:46.673 に答える
1

インサートの代わりにCOPYを使用しようと思います。これは、バックアップツールが高速読み込みに使用するものです。

このテーブルのすべての外部キーに、ターゲットテーブルに対応するインデックスがあるかどうかを確認します。または、コピーする前に一時的にドロップして、後で再作成することをお勧めします。

checkpoint_segmentsをデフォルトの3(つまり、3 * 16MB = 48MB)からはるかに高い数に増やします。たとえば、32(512MB)を試してください。この多くの追加データのために十分なスペースがあることを確認してください。

システムクラッシュや電源障害が発生した場合にデータベースクラスターを最初から再作成または復元する余裕がある場合は、「-F」オプションを指定してPostgresを起動できます。これにより、OS書き込みキャッシュが有効になります。

于 2011-02-11T14:22:26.010 に答える
1

このトピックに関するヒントのリストは、ドキュメントのデータベースへの入力セクションにあります。PostgreSQL サーバーのチューニングのヒントを使用して、一般的なパフォーマンスを高速化することもできます。

テーブルのサイズが大きくなるにつれて、外部キーをチェックするオーバーヘッドが大きくなる可能性があります。これは、一度に 1 つのレコードをロードするため、さらに悪化します。70GB 相当のデータをロードする場合、ロード中に外部キーを削除し、インポート時に再構築する方がはるかに高速です。これは、単一の INSERT ステートメントを使用している場合に特に当てはまります。代わりに COPY に切り替えることは、保留中のトリガー キューがどのように管理されるかにより、保証された改善ではありません。問題については、最初のドキュメント リンクで説明されています。

psql プロンプトから、外部キーを強制する制約の名前を見つけて、次のようにその名前を使用してドロップできます。

\d tablename
ALTER TABLE tablename DROP CONSTRAINT constraint_name;

ロードが完了したら、次のようなものを使用して元に戻すことができます。

ALTER TABLE tablename ADD CONSTRAINT constraint_name FOREIGN KEY (other_table) REFERENCES other_table (join_column);

復元に使用する正確な構文を見つけるための便利な方法の 1 つは、データベースでpg_dump --schema-onlyを実行することです。それからのダンプは、現在の構造を再作成する方法を示します。

于 2011-02-15T17:03:50.077 に答える
1

http://pgbulkload.projects.postgresql.org/をご覧ください。

于 2011-02-13T02:35:00.823 に答える
0

ロールバックログを確認します。これを1つのトランザクションで実行する場合、それらはかなり大きくなる必要があります。

その場合は、トランザクションのバッチサイズを小さくしてみてください。レコードの小さなブロック(1K、10K、100Kなど)にチャンクして、それが役立つかどうかを確認します。

于 2011-02-11T12:16:40.180 に答える
0

最初の 5 ミルの行は何もありません。挿入の違いは 100k であろうと 1 ミルであろうと変わらないはずです。1 ~ 2 個のインデックスを使用してもそれほど遅くなることはありません (fill factor が 70 ~ 90 に設定されている場合、各主要なインポートが table の 1/10 であることを考慮してください)。

PSYCOPG2 を使用した python は非常に高速です。ちょっとしたヒントとして、データベース拡張 XML2 を使用してデータを読み取ったり操作したりできます

https://dba.stackexchange.com/questions/8172/sql-to-read-xml-from-file-into-postgresql-databaseの小さな例

duffymo の言うとおりです。10000 回の挿入のチャンクでコミットしてみてください (最後または各挿入後にのみコミットすると、非常にコストがかかります)。大量の削除と更新を行うと、自動バキュームが肥大化する可能性があります。開始時に一時的にオフにすることができます。特定のテーブル。サーバーの利用可能なリソースに応じてwork_memとmaintenance_work_memを設定します...挿入の場合、wal_buffersを増やします(9.0以降はデフォルトでautoに設定されています-1)バージョン8のpostgresqlを使用する場合は、手動で増やす必要がありますcudまたfsyncをオフにしてテストしますwal_sync_method (これを変更すると、突然の電源障害やハードウェア クラッシュが発生した場合にデータベースがクラッシュする可能性があることに注意してください)

外部キーの削除、トリガーの無効化、またはトリガーを実行しない/実行をスキップする条件の設定を試みます。

挿入に準備済みステートメントを使用し、変数をキャストする

データを一時的に保持するために、ログに記録されていないテーブルにデータを挿入しようとする

挿入は、サブクエリ、関数などからの条件または値を持っていますか?

于 2013-03-01T14:37:39.017 に答える