3

要件: テーブル全体をスキャンし、すべてのレコード、期間を更新する必要があります。

他の人が示唆したように、元のスキーマと同じスキーマを持つ一時テーブルを作成し、更新された値に挿入してから、元のテーブルを更新する代わりにテーブルの名前を変更する必要があります。

アイデアは次のようなものです。

ResultSet row = select * from old_table;
While row.next
  do something to update values in this row
  insert updated values in to a identical table (different name of course)
endWhile

ここでの質問は、Java JDBC を使用しており、ResultSet オブジェクトを処理する必要があるということです。「ResultSet row = select * from old_table」がメモリ不足の例外を生成するのを防ぐ方法はありますか?

潜在的な解決策はページングですが、それは ORDER BY と LIMIT を使用する必要があることを意味します。これは、300 万行のテーブルでは非常に遅くなる可能性があります。

FOWARD_ONLY | のようないくつかのフラグを指定するなど、ResultSet にトリックはありますか? NON-SCROLLABLEなど。または、Mysqlサーバーには、完全なテーブルスキャンを実行していることをmysqlが理解しているようなスマートなことを行うための構成があるので、レコードを順番に返しますが、一度にすべてではありません。

どんな提案でも大歓迎です

[更新] MySQL connector/J には という構成パラメーターがuseCursorFetchあるようです。true に設定すると機能しstatement.setFetchSize(1000)ます。これが究極の解決策かどうかはわかりません。

4

1 に答える 1

1

次の方法で、JDBC ステートメントを非バッファに設定できます。

stmt.setFetchSize(Integer.MIN_VALUE); 

ただし、INSERT... SELECTステートメントを使用するように結合することもお勧めします。そのため、while ループを使用する必要がなく、何もフェッチする必要がありません。「値を更新するために何かをする」というステップにSQL式を使用できる場合は、1つのSQLステートメントで操作全体を実行できます。

PS: QuerySet についてより具体的に説明する必要があります。org.dbunit.ant.QuerySet、org.gusdb.wdk.model.QuerySet など、さまざまなライブラリで QuerySet と呼ばれる複数のクラスを見つけました。

于 2013-09-15T22:16:36.503 に答える