1

私はPythonでpsycopg2を使用していますが、私の質問はDBMSに依存しません(DBMSがトランザクションをサポートしている限り):

私はデータベーステーブルにレコードを挿入するPythonプログラムを書いています。挿入されるレコードの数は100万を超えています。各挿入ステートメントでコミットを実行するようにコードを記述したとき、プログラムが遅すぎました。したがって、5000レコードごとにコミットを実行するようにコードを変更しましたが、速度の違いは非常に大きかったです。

私の問題は、ある時点でレコードの挿入時に例外が発生し(一部の整合性チェックが失敗する)、例外が発生した最後のコマンドを除いて、その時点まで変更をコミットし、残りを続行したいということです。私の挿入ステートメントの。

私はこれを達成する方法を見つけていません。私が達成した唯一のことは、例外をキャプチャし、トランザクションをロールバックして、保留中の挿入ステートメントを失うその時点から続行することでした。また、カーソルオブジェクトと接続オブジェクトも運が悪かったので(ディープ)コピーしてみました。

ステートメントをロールバックして再作成/再実行することなく、この機能を直接または間接的に実現する方法はありますか?

よろしくお願いします、

ジョージ。

4

2 に答える 2

3

これを行うための高速なクロスデータベースの方法が見つかるとは思えません。バッチサイズによる速度の向上と、エントリによってバッチが失敗した場合に作業を繰り返す速度のコストとのバランスを最適化する必要があります。

一部のDBはエラー後にトランザクションを続行できますが、PostgreSQLは続行できません。ただし、SAVEPOINTコマンドを使用してサブトランザクションを作成することはできます。これらは無料にはほど遠いですが、完全なトランザクションよりも低コストです。したがって、実行できるのは、(たとえば)100行ごとに、を発行してSAVEPOINTから、前のセーブポイントを解放することです。エラーが発生した場合はROLLBACK TO SAVEPOINT、コミットしてから、中断したところから再開します。

于 2012-12-12T11:29:02.007 に答える
2

5000レコード間隔ごとにトランザクションをコミットしている場合は、入力データの前処理を少し行って、実際に5000レコードチャンクのリストに分割できるようです。[[[row1_data],[row2_data]...[row4999_data]],[[row5000_data],[row5001_data],...],[[....[row1000000_data]]]

次に、挿入を実行し、処理しているチャンクと現在挿入しているレコードを追跡します。エラーが発生した場合は、チャンクを再実行しますが、問題のあるレコードはスキップします。

于 2012-12-12T22:38:33.227 に答える