2011-10-06 18 views
1

私は9200万行のテーブルがあります。私はそのテーブルからデータを更新する必要がある4000のIDのリストを持っています。私は自分のテーブルに4000個のIDを入れて、以下を実行しようとしました:効率的な方法は、db2データベースの行を更新する

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

これはメモリの制約のために落ちます。だから私は4000個のIDをそれぞれ1000個の4つのテーブルに分割しようとしました。そのような大きなテーブルを扱う最も効率的な方法は何ですか?

ありがとうございました。

+0

1000より小さいチャンクを試しましたか?また、 'idstoupdate'テーブルを1つだけ使用して、対応する' where'句をサブクエリに追加することもできます。 – michael667

+0

これは、129milの行テーブルで同等の文を実行することができます(instantaneuosレスポンス)ので、これはハードウェアの問題(十分ではない)です。また、 'clients'の' id'にインデックスがあることを教えてください... –

+0

あなたがデータベースから得た実際のエラーメッセージを投稿してください。 –

答えて

4

ファンシーなサブセレクトを使用してテーブルを別のテーブルに更新する方法があるかもしれませんが、SQL APIを使用してこれを行うプログラムを作成するのが最善の方法です(DBI :: DB2ドライバperl、JDBC for Java、またはCライブラリなど)を使用して、SELECTを実行し、RESULTSETの各結果行をカーソルでFETCHして更新します。

擬似コードは(私はあなたが精通しているどのような言語を知らない):

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を持つ別のテーブルからテーブルを更新する必要がある場合は

IN述語を排除し、おそらくあまり多くのメモリやログ・スペースである

 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' 
      )  

効率的で、選択、ループ、フェッチ、更新よりも単純ではないため、すべての基準が正しいことを確認する必要があります。あなたの場合は、私はこれが仕事だと思うsimpler--少しですが、私はに対してそれを試して、DB2インスタンスを必要とするだろう:

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

編集: は、私はあなたが与えたクエリがなかったことを、実際に驚いていますそれは正当なクエリであるので、SQLリスから作業してください。 DB2はSQLの最適化/最適なアクセス・パスの決定に非常に優れているため、これは私が与えた例と似ています。

私の答えでは、テーブルを更新する最もメモリ効率の高い方法と、純粋なSQLを使用して別のテーブルから1つのテーブルの行を更新する一般的なパターンを表示しようとしていました更新したい行だけではありません)。

さらに、現代のデータベースエンジンがそれらを容易に処理しても、20以上の値を含むIN述語が疑わしいです。

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

+0

@edwardmlyteこの種の更新のもう1つのアプローチは、[MERGE](http://publib.boulder.ibm.com/infocenter/db2luw/v9/index.jsp?topic=/com.ibm.db2.udb .admin.doc/doc/r0010873.htm)ステートメント。これはDB2の比較的新しい機能です。DB2 8.2で導入されたと思います。 MERGEステートメントは、他者があなたの意図を知る最も明瞭な方法かもしれません。あなたのニーズには過度のものかもしれませんが、それは良いパターンです。 – mwolfetech

1

私が実際に投稿したクエリはうまく動作します。私の問題は、直接入力を使用してデータベースに問い合わせるのとは反対に、外部プログラムを使用してデータベースを照会することによって発生していました。誤って通知された質問を申し訳ありません。

関連する問題