2017-05-11 9 views
0

私は設計上の問題があります。私は更新する必要がある何百万ものレコードを持つデータベースを持っています。JDBC Oracleデータベースの数百万のレコードを更新します

新しいフィールド値を計算するために何らかの処理を行う必要があるため、JDBCを使用します。

もう一度やり直してもらえません。だから私は単純なことを考えていた。私は新しいテーブルを作成して古いものを削除したいと思っていましたが、DBAは望んでいません。ストレージの必要性が大きいからです。

私は約80百万行を処理し、各行は3フィールドを更新する必要があります。

たとえば、setFetchSize(1000)を使用した単純なjdbcアプローチが有効でしょうか?

私は、更新のためにmutableからa、b、cを選択することを意味します。 その後の更新...

JDBCプログラムは作業負荷をサポートできますか?

また、SpringBatchまたはEasyBatchの使用についても考えていました。しかし、私はそれがちょうど1つのゴー(そしていくつかの非常に短いタイムライン)のためにこれで時間を調べる価値があるかどうか疑問に思っています。

これはあなたの経験ですか?

+0

は、データベースに含まれるすべての更新を行うために必要な情報ですか? (数式が使用されています)、または処理が完了しなければならないと言ったときには、更新に必要な情報の一部がローカルなのですからですか? – xQbert

+0

こんにちは。更新情報はデータベースに含まれていません。私は、データ行を読み取って、計算された値を取得するために外部サービスを呼び出して、計算された値で行の3フィールドを更新する必要があります。 – Gilles

+1

@ Gillesこれはどれくらいの時間を必要としますか?あなたはjavaと各行に対してデータを取り込み、外部サービスを呼び出してデータベースを更新します。これを行ごとに10ミリ秒で行うことができますか、私はあなたができるとは思っていませんが、プロセスを完了するのにまだ9.25日かかります。それをそこから拡張する。行ごとに100msかかる場合は、今は92.5日です。それがこのように行われなければならない場合は、あなたが何を得るかを知ることが最善です。 – unleashed

答えて

0

私はJDBCでこれを行うことができると思います。私は次のようなものを提案します:

  • 2つまたは3つのスレッドを作成します。各スレッドは以下を実行します
  • 接続を作成します。
  • 行の互いに素なサブセットを取得するプリペアドステートメントを作成します。
  • フェッチサイズを100程度に設定します。確かに1000未満
  • は、実行結果が、各行について
  • を更新した後、サイズ行がバッチを実行フェッチするバッチを追加セットに対してクエリ
  • 反復を更新ステートメント
  • を作成

フェッチサイズを100と仮定します。最初の実行は往復を行い、時間がかかります。それが起こっている間に別のスレッドを実行してください。実行が戻ると、次の100行はデータベース往復を行いません。行はすでにフェッチされており、更新はバッチ処理されているため、データベースのラウンドトリップは行われません。 100行がバッチを実行すると、ラウンドトリップが行われ、スレッドが切り替わります。その後、スレッドを切り替える100以上の行をフェッチします。私は2つか3つのスレッドが最適かどうかは分かりませんが、もし私が推測しなければ3つを試してみる必要があります。

しかし、上記の説明では、マシンは1つのハードウェアスレッドしか持っていないものとします。ほとんどのCPUは12個以上のハードウェアスレッドをサポートしているので、ハードウェアがサポートできるものに応じて実際には30個程度のスレッドを使用します。複数のCPUを使用している場合でも、おそらくデータベースに競合が導入されるように50以上のスレッドを必要としません。

上記は、外部サービスが高速で、データベースよりもはるかに高速であることを前提としています。そうでなければ、各行を処理することは外部サービスを待つことになります。その場合、より多くのスレッド。更新がデータベースにヒットする時間が遅くなるため、データベース内のスレッドの競合は問題になりません。次のように互いに素なサブセットにクエリ結果を分割する

1つの方法である:そして

SELECT c1, c2, etc, row 
FROM (SELECT c1, c2, etc, ROWNUM FROM ...) 
WHERE MOD(row, number_of_partitions) = ? 

0からnumber_of_partitionsにクエリPARAMを設定 - 1、スレッドごとに1つずつ。 ROWNUMを正しく動作させるには、これをサブクエリとして実行する必要があります。

更新可能な結果セットを使用しないでください。パフォーマンスは保証されています。

関連する問題