sql >> データベース >  >> RDS >> PostgreSQL

PostgreSQLで挿入パフォーマンスを高速化する方法

    PostgreSQLマニュアルのデータベースへの入力、このトピックに関するdepeszの通常どおりの優れた記事、およびこのSOの質問を参照してください。

    (この回答は、既存のDBへのデータの一括読み込み、または新しいDBの作成に関するものであることに注意してください。 pg_restoreを使用したDB復元のパフォーマンスに関心がある場合 またはpsql pg_dumpの実行 出力、 pg_dump 以降、これの多くは適用されません およびpg_restore スキーマとデータの復元が完了した後、トリガーやインデックスを作成するなどの作業をすでに行っています)

    やるべきことがたくさんあります。理想的な解決策は、 UNLOGGEDにインポートすることです。 インデックスのないテーブルをログに記録するように変更し、インデックスを追加します。残念ながら、PostgreSQL 9.4では、テーブルを UNLOGGEDから変更することはサポートされていません。 ログに記録します。 9.5はALTERTABLE ... SET LOGGEDを追加します これを許可するため。

    一括インポートのためにデータベースをオフラインにできる場合は、 pg_bulkloadを使用してください 。

    それ以外の場合:

    • テーブルのトリガーを無効にします

    • インポートを開始する前にインデックスを削除し、後で再作成します。 (多くの 同じデータを段階的に追加するよりも、1回のパスでインデックスを作成する時間が短くなり、結果のインデックスははるかにコンパクトになります。

    • 単一のトランザクション内でインポートを実行する場合は、外部キー制約を削除し、インポートを実行して、コミットする前に制約を再作成しても安全です。インポートが複数のトランザクションに分割されている場合は、無効なデータが導入される可能性があるため、これを行わないでください。

    • 可能であれば、 COPYを使用してください INSERTの代わりに s

    • COPYを使用できない場合 複数値のINSERTの使用を検討してください s実用的な場合。あなたはすでにこれをしているようです。 あまりにもリストしようとしないでください 1つのVALUESに多数の値 けれど;これらの値はメモリに数回収まる必要があるため、ステートメントごとに数百に抑えてください。

    • 挿入を明示的なトランザクションにバッチ処理し、トランザクションごとに数十万または数百万の挿入を実行します。 AFAIKに実際的な制限はありませんが、バッチ処理を使用すると、入力データの各バッチの開始をマークすることでエラーから回復できます。繰り返しますが、あなたはすでにこれを行っているようです。

    • synchronous_commit =offを使用します そして巨大なcommit_delay fsync()のコストを削減します。ただし、作業を大きなトランザクションにまとめた場合、これはあまり役に立ちません。

    • INSERT またはCOPY 複数の接続から並列に。いくつはハードウェアのディスクサブシステムによって異なります。経験則として、直接接続ストレージを使用する場合は、物理ハードドライブごとに1つの接続が必要です。

    • max_wal_sizeを高く設定します 値( checkpoint_segments 古いバージョンの場合)、 log_checkpointsを有効にします 。 PostgreSQLのログを見て、チェックポイントが頻繁に発生することについて不平を言っていないことを確認してください。

    • インポート中にシステムがクラッシュした場合にPostgreSQLクラスター全体(データベースと同じクラスター上の他のデータベース)を壊滅的な破損で失ってもかまわない場合にのみ、Pgを停止し、 fsync =off 、Pgを起動し、インポートを実行してから、(仮想的に)Pgを停止し、 fsync =onを設定します。 また。 WAL構成を参照してください。 PostgreSQLインストールのデータベースに気になるデータがすでにある場合は、これを行わないでください。 fsync =offを設定した場合 full_page_writes =offを設定することもできます;繰り返しになりますが、データベースの破損やデータの損失を防ぐために、インポート後にオンに戻すことを忘れないでください。 Pgマニュアルの非耐久性設定を参照してください。

    システムの調整も検討する必要があります:

    • 高品質を使用する 可能な限りストレージ用のSSD。信頼性が高く、電力が保護されたライトバックキャッシュを備えた優れたSSDは、コミットレートを信じられないほど速くします。上記のアドバイスに従うと、メリットが少なくなります。これにより、ディスクのフラッシュ/ fsync()の数が減ります。 s-しかし、それでも大きな助けになる可能性があります。データの保持を気にしない限り、適切な停電保護なしで安価なSSDを使用しないでください。

    • 直接接続ストレージにRAID5またはRAID6を使用している場合は、ここで停止します。データをバックアップし、RAIDアレイをRAID 10に再構築して、再試行してください。 RAID 5/6は、一括書き込みのパフォーマンスには絶望的ですが、大きなキャッシュを備えた優れたRAIDコントローラーが役立ちます。

    • バッテリでバックアップされた大きなライトバックキャッシュを備えたハードウェアRAIDコントローラを使用するオプションがある場合、これにより、コミットが多いワークロードの書き込みパフォーマンスを大幅に向上させることができます。 commit_delayで非同期コミットを使用している場合やバルクロード中に実行する大きなトランザクションが少ない場合は、それほど役に立ちません。

    • 可能であれば、WAL( pg_wal 、または pg_xlog 古いバージョンでは)別のディスク/ディスクアレイ上。同じディスク上で別のファイルシステムを使用する意味はほとんどありません。多くの場合、WALにはRAID1ペアを使用することを選択します。繰り返しになりますが、これはコミット率の高いシステムにより大きな影響を及ぼし、ログに記録されていないテーブルをデータロードターゲットとして使用している場合はほとんど効果がありません。

    また、高速テストのためにPostgreSQLを最適化することにも興味があるかもしれません。



    1. PostgreSQLの時間値に時間を追加する

    2. IF/ELSEステートメントを使用してSQLで新しいxmlノードエントリを更新または作成する方法

    3. 新しいSQLレコードIDを取得します

    4. テーブル式の基礎、パート7 – CTE、最適化の考慮事項