Java プログラムを使用して、あるデータベース (oracle) から別のデータベース (postgres) に大量のデータ (ほぼ 1000 万レコード) を転送する必要があります。2 つの DB との接続を作成して同じことを行い、ソース データベースからデータをクエリしてから、結果セットを反復してデータを宛先データベースに挿入しました。しかし、データの転送には膨大な時間がかかります。転送プロセスを迅速に行う方法はありますか?
3 に答える
1 つの代替方法は、テーブル内のすべてのデータをテキスト ファイルにエクスポートしてから、そのデータを直接 postgres にインポートすることです。オラクルにどのようなエクスポート機能があるかは覚えていませんが、最悪の場合、常に次のようなクエリを使用して、テーブルの内容を一連の挿入ステートメントとしてダンプできます。
select 'insert into mynewtable values(' || old.a || ', ' || old.b || ...etc..|| ');' myoldtable old から;
私は間違いなく、Oracle データベース (Java を使用) から 1,000 万件のレコードを数時間で処理しました (各レコード間で多くの処理が行われます)。どのようなパフォーマンスを期待し、現在何を得ていますか?
postgres テーブルに挿入するときに、多くのインデックスや制約をチェックしていますか? 多分あなたのコードに何か問題がありますか?すべての行が有効であることがわかっている場合は、挿入中に postgres db の制約を削除する必要がありますか?
または、しばらくしていない場合は、データベースをバキュームする必要がありますか?
シングルスレッドのデータ読み取り、データ書き込みに制限されている場合、改善の余地はあまりありません。
このタイプのパフォーマンスは、ネットワークを介して移動するデータの量、ネットワークの速度、データベースのインデックス作成と構成、およびネットワーク/ホスト内のその他の要因など、いくつかの異なる要因によって制限されます。
少なくとも、より大きなフェッチサイズで読み取り接続を設定する必要があります。
ResultSet rs;
...
rs.setFetchSize(500);
挿入側では、CallableStatement を使用したバッチ処理も検討する必要があります
CallableStatement cs;
Connection conn;
conn.setAutoCommit(false);
...
cs.addBatch();
if (rowCount % batchsize == 0) {
int[] updateCounts = cs.executeBatch();
conn.commit();
batchCount = 0;
for (int i = 0; i < updateCounts.length; i++) {
if (updateCounts[i] < 1)
bad.write(batchRec[i]);
}
}
挿入のパフォーマンスのために Oracle でできることは他にもあります。そのうちの 1 つは、名前付きパイプを使用してバルク ロードを設定することです。その後、プロセスはその名前付きパイプに書き込むことができます。それらはログに記録されない操作であるため、かなり高速です。私はJavaから名前付きパイプのことをしていないので、調べる必要がありますが、それでうまくいくはずです。
ボトルネックがどこにあるかを把握する必要があります。クエリが一部のテーブルのテーブル スキャンであり、後の行のデータを取得するのに前の行よりも時間がかかるため、時間の経過とともにパフォーマンスが低下するのを見てきました。
他のものと同様に、選択に時間がかかり始めるかどうか、または読み取りパフォーマンスがかなり安定しているかどうかを確認するために、タイミングの導入を開始する必要があります (後の行フェッチが前の行フェッチよりも長くかかる場合は、テーブル スキャンの良い兆候です)。
最後に、クエリをうまく分解できれば、複数のワーカー スレッドを使用してデータを並列処理できます。
すなわち。それ以外の
select a,b,c from source table
あなたはそれを次のように分解します
select a,b,c from source table where a < 10;
select a,b,c from source_table where a >= 10 and a < 50;
select a,b,c from source_table where a >= 50;
他のものと同様に、物事を行う方法は 100 通りあります。
ここでの問題は、プログラミング言語がカーソルを使用してタプルのセットを処理することです。カーソルはそれらを反復処理することしかできず、一括読み込みなどを行うことはできません。これはすべてのプログラミング言語に当てはまります。より高速なソリューションは、Oracle を PostgreSQL に接続することです。 、それを行う方法はわかりませんが、可能だと思います。すべてにOracle関数があります。