bugfix> sql > 投稿

最初の数千回の挿入の後、PostgreSQLデータベースへの挿入速度が徐々に低下しているため、これが発生する理由についての説明を見つけることができませんでした。おそらく誰かがこれを説明するのを助けることができる:

問題は次のとおりです。

JSON配列をSQL挿入ステートメントに、外部キーで接続された2つのテーブルに、すべて単一のトランザクションで解析します。エラー時には、エラーのあるエントリのみがロールバックされます(そのため、接続されたテーブルに孤立データはありません)。

わずかな注意点は、これらのINSERTが汎用であると想定されていることです(ユーザーが提供したデータをシステムに動的にロードするツールを構築します)。

したがって、私の解決策は、ファイルの先頭でトランザクションを開始し、すべてのエントリのセーブポイントを作成することです。そのエントリにエラーがある場合、トランザクションはそのセーブポイントにロールバックされ(そしてセーブポイントが解放されます)、エラーがなければ、セーブポイントが解放されてインポ​​ートが続行されます。

挿入するレコードが数万または数十万になるまで、これはかなりうまく機能します。最初の数千は非常にうまくいき、1秒あたり300から400の間で挿入されますが、徐々に減速し始めます。

Done 200, rate 200/s, succeeded 200 failed 0
Done 300, rate 300/s, succeeded 300 failed 0
Done 400, rate 400/s, succeeded 400 failed 0
Done 500, rate 250/s, succeeded 500 failed 0
Done 600, rate 300/s, succeeded 599 failed 1
Done 700, rate 233/s, succeeded 699 failed 1
Done 800, rate 266/s, succeeded 799 failed 1
Done 900, rate 300/s, succeeded 899 failed 1
Done 1000, rate 250/s, succeeded 999 failed 1
Done 1100, rate 275/s, succeeded 1099 failed 1
...
Done 5200, rate 185/s, succeeded 5195 failed 5
Done 5300, rate 182/s, succeeded 5295 failed 5
Done 5400, rate 186/s, succeeded 5395 failed 5
Done 5500, rate 183/s, succeeded 5495 failed 5
...
Done 31000, rate 58/s, succeeded 30953 failed 47
Done 31100, rate 58/s, succeeded 31053 failed 47
Done 31200, rate 57/s, succeeded 31153 failed 47

したがって、30.000の挿入後、開始時の1/5にまでスローダウンしました。 テーブルは、いくつかのVARCHAR、いくつかの数値、主キー、および外部キーを持つ非常に単純なテーブルです。関数、トリガーなどはありません。

JDBCに、不要になったリソースを保持していて、問題を引き起こしている可能性のあるものがあるかどうか疑問に思っています。確かに300 /秒で始まる場合、コード、ネットワーク、およびDBサーバーは少なくともそれをサポートできます。

バッチ処理により劇的に改善されることはわかっていますが、ここで説明したユースケースでは機能しません。

回答 1 件
  • 「セーブポイントを解放」しても、データベースはトランザクションが終了するまでメモリ構造を保持します。実際に行をコミットしますか?

    バッチAPIを使用し、バッチステートメントの前にセーブポイントを使用することもできます。たとえば、100個のバッチを使用し、失敗した場合は1つずつ再試行できます。または、バッチ50で再試行します。これにより、バッチAPIが有効になり、必要なセーブポイントの数が減り、無効な行などをスキップできます。

    バックエンド側での高いメモリ消費を避けるために、時々トランザクションをコミットしたい場合があります。

    上記が役に立たない場合は、先に進み、データベースプロセスのプロファイルを作成します(例: perf 経由) )ボトルネックの原因を確認します。

あなたの答え