1

9,200 万行のテーブルがあります。そのテーブルから、データの更新が必要な 4000 個の ID のリストがあります。4000 個の ID を独自のテーブルに入れ、次を実行してみました。

update clients
set col1='1', col2='y'
where id in
(select id from idstoupdate)

しかし、これはメモリの制約により失敗します。そこで、4000 個の ID をそれぞれ 1000 個の 4 つのテーブルに分割しようとしましたが、それらの小さなテーブルで試してみると、まだ失敗しています。このような大きなテーブルを処理する最も効率的な方法は何ですか?

ありがとう。

4

2 に答える 2

4

ファンシーな副選択を介してテーブルを別のテーブルで更新する方法があるかもしれませんが、最良のアプローチは、SQL API を使用してこれを行うプログラムを作成することだと思います (perl の場合は DBD::DB2 ドライバーを使用する DBI、 Java、または C ライブラリなど) を使用して SELECT を実行し、カーソルを使用して RESULTSET から各結果行をフェッチし、更新を行います。

PSEUDOCODE (あなたがよく知っている言語はわかりません):

dbHandle = sqllib->open_connection(database, user, password) 
select_statement = dbHandle->prepare('SELECT id FROM idstoupdate')
update_statement = dbHandle->prepare('UPDATE clients SET col1=?, col2=? WHERE ID=?')
resultset = statement->execute(select_statement)

foreach (row in resultset) {
  id = row.getColumn('id')
  update_statement->execute('1','2',id) 
}

dbHandle->disconnect();  

エラーチェックを追加する必要があります。すべての更新を適用するか、まったく適用しない場合は、トランザクションを開始し、エラーがなければトランザクション全体をコミットする必要があります。DB2 Infocenterには、上記のすべてを行う方法に関する豊富な資料があります。

注: のソース データがidstoupdateファイルの場合は、select ステートメントとidstoupdateテーブルをロードする作業をスキップして、ファイルから読み取ってデータベースを更新するだけでかまいません。これは、テーブルの更新を処理する最も効率的な方法です。

単純に純粋な SQL を使用して別のテーブルからテーブルを更新する必要がある場合、最も一般的な例は次の形式です。

      UPDATE table1 t1
         SET (t1.field1, t1.field2) = 
             (
               SELECT t2.field1, 
                      t2.field2
                 FROM table2 t2
                WHERE t1.joinfield = t2.joinfield 
                  AND t2.criteriafield = 'qualifier'
             )
       WHERE EXISTS 
             ( 
               SELECT 1 
                 FROM table2
                WHERE t1.joinfield = table2.joinfield 
                  AND t2.criteriafield = 'qualifier'
             )    

これにより述語が削除されますINが、おそらくメモリやログスペースの効率はそれほど向上しません。また、選択、ループ、フェッチ、更新よりも単純ではないため、すべての基準が正しいことを確認する必要があります。あなたのケースは少し単純です-これはうまくいくと思いますが、それを試すにはdb2インスタンスが必要です:

      UPDATE clients t1
         SET t1.col1 = '1', col2 = 'y' 
       WHERE EXISTS 
             ( 
               SELECT 1 
                 FROM idstoupdate t2
                WHERE t1.id = t2.id 
             )  

編集: あなたが与えたクエリが正当なクエリであるため、SQL squirrelから機能しなかったことに実際に驚いています。DB2 は SQL の最適化や最適なアクセス パスの決定に非常に優れているため、私が示した例と同じように機能することさえあります。

私の答えでは、テーブルを更新する最もメモリ効率の良い方法と、純粋な SQL を使用してあるテーブルの行を別のテーブルから更新する一般的なパターンを示そうとしていました (これは、1 つのテーブルに更新する行)。

さらに、最新のデータベース エンジンが簡単に処理できるとしても、20 を超える値を含む IN 述語には疑いがあります。

ただし、データベース エンジンがクエリを効率的に処理しているかどうかを調べたり、2 つの SQL クエリを比較したりする最善の方法は、SQL 説明コマンドを使用することです。

于 2011-10-06T16:40:18.973 に答える
1

私が投稿したクエリは、実際には正常に動作します。私の問題は、直接入力を使用してデータベースを照会するのではなく、外部プログラムを使用してデータベースを照会することによって引き起こされていました。間違った情報に基づいた質問で申し訳ありません。

于 2011-10-07T07:50:50.557 に答える