2012-05-10 9 views
0

Javaプログラムを使用して1つのデータベース(オラクル)から別のデータベース(ポストグル)に大量のデータ(約1,000万レコード)を転送する必要があります。私は2つのDBとの接続を作成して同じことを行い、ソースdbからデータを照会し、結果セットを反復することによってデータを宛先dbに挿入しました。しかし、データの転送には膨大な時間がかかります。転送プロセスを迅速に行う方法はありますか?Javaを使用して膨大なデータを転送する

+0

Spring Batchフレームワークを使用して、ファイルをチャンクに分割して処理することができます。 – Seshagiri

+0

あなたはこの男と同じ問題に直面しています>>> http://www.coderanch.com/t/470765/JDBC/java/Transfer-Huge-data-Java –

+0

なぜJavaを使用する必要がありますか? Oracleはファイルへのエクスポートをサポートしており、Postgresはファイルからのインポートをサポートしています。 Javaはこのタスクのための私の最初の選択ではないでしょう。 – EJP

答えて

0

ここでの問題は、プログラミング言語がタプルのセットを処理するためにカーソルを使用することです。カーソルはそれらを反復することしかできません。そのようなバルクロードなどはできません。これはすべてのプログラミング言語を考えると、 OracleをPostgreSQLにどうにかして、私はそれをどうやって行うのかはわかりませんが、可能でなければならないと思います。すべてのOracle機能があります。

1

代わりに、テーブルのすべてのデータをテキストファイルにエクスポートし、そのデータを直接ポストグルにインポートすることもできます。 oracleのエクスポート機能が何であるか覚えていませんが、最悪の場合、常にこのような問合せを使用して、表の内容をinsert文のセットとしてダンプしてください:

「insert into mynewtable values | old.a || '、' || old.b || ...など。|| ');' myoldtable古いから;

私は間違いなく、Javaデータベースを使用して数時間以内に各レコード間で多くの処理を行うことで10MMレコードを処理しました。あなたはどんなパフォーマンスを望んでいますか、今何を得ていますか?

postgresテーブルに挿入する際に、多くのインデックスや制約がチェックされていますか?他の何かがあなたのコードに間違っているのでしょうか?すべての行が有効であることがわかっている場合は、挿入を実行中にpostgres dbに制約をドロップする必要がありますか?

また、しばらくお待ちください、データベースを掃除する必要がありますか?

+0

今、私はちょうどpostgresから選択したいくつかのwhere節を使用して、oracleから多くのレコードを読み込み、postgresに選択されたレコードをすべて挿入し直しています。 – satheesh

1

シングルスレッドの読み取りデータに限定してデータを書き込む場合、改善の余地はあまりありません。

このタイプのパフォーマンスは、ネットワーク経由で移動するデータの量、ネットワークの速度、データベースのインデックスと構成、およびネットワーク/ホスト内の他のいくつかのものによって、制限されます。

少なくとも、より大きなフェッチサイズで読み込み接続を設定する必要があります。挿入側で

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]); 
    } 
} 

を使用してバッチ処理をご覧ください名前付きパイプを使用すると、プロセスはその名前付きパイプに書き込むことができます。これらはログに記録されない操作なので、かなり高速です。私はJavaから名前付きパイプのことをしていないので、調べるべきことですが、それはあなたを動かすはずです。

ボトルネックがどこにあるか把握する必要があります。私は時間が経つにつれてパフォーマンスが低下するのを見ました。なぜなら、クエリはテーブルのテーブルスキャンであり、以前の行よりも後の行のデータを取得するのに時間がかかります。

他のものと同様にタイミングを導入して、選択に時間がかかるか、読み込みパフォーマンスがかなり安定しているかどうかを確認する必要があります(後のローのフェッチが早くなる行のフェッチ)。

最後に、クエリをきれいに分割することができれば、複数のワーカースレッドを使用してデータを並行して処理することができます。

ie。代わりに

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; 

のようにそれを打破するだろう、物事を行うには百通りの方法があります。

関連する問題