web-dev-qa-db-ja.com

どちらが速いですか?カーソルループ内の複数の更新クエリ、または単一のクエリ?

どちらが速いですか?カーソルループ内の複数の更新クエリ、または単一のクエリ?たとえば、この場合、どちらが速いですか?このクエリはトリガー内にあります。

  1. ループ内の複数のクエリ

    DECLARE done INT DEFAULT FALSE;
    DECLARE record_id INT;
    DECLARE cur CURSOR FOR SELECT id FROM table1 WHERE column = 0;
    
    OPEN cur;
    
      users_loop: LOOP
    
         FETCH cur INTO id;
    
         IF done THEN
             LEAVE users_loop;
         END IF;
    
         UPDATE table2 SET column = 0 WHERE id = id;
    
      END LOOP;
    
    CLOSE cur;
    
  2. 単一クエリ

     CREATE TEMPORARY TABLE tmp_table (id int(10));
    
     INSERT INTO tmp_table SELECT id FROM table1 WHERE column = 0;
    
     UPDATE table2 SET column = 0 WHERE id IN(SELECT id FROM temp_table);
    
     DROP TABLE IF EXISTS tmp_table;
    
6
Pelang

それは多くの要因に依存します:

  • テーブル定義
  • インデックスの定義
  • トランザクション分離レベル
  • 一般的なデータベースの負荷
  • 利用可能なメモリ
  • ...

十分なメモリ、プロセッサ能力、一時テーブルスペースがある場合、2番目のステートメントが最も高速になりますが、一度に大量のロックが発生するという欠点があります。

InnoDBのさまざまなSQLステートメントによって設定されるロック

最初のステートメントを実行すると、他のすべてのユーザーのロックが少なくなる可能性がありますが、データベースに接続しているユーザーのトランザクション分離レベルに依存します。

トランザクション分離レベル

ご覧のとおり、更新ステートメントの実行に影響を与える可能性のある要因は多数あります。

詳細がなければ、速度を上げるために2番目のステートメントを使用し、最初のステートメントは負荷のある環境で使用します。

同様の質問がここで尋ねられました:

MySQLでロックせずに(非常に)大きなテーブルを更新する方法

2

どちらも-3番目のオプションを提示する必要があります。

オプション1は、ストアドルーチンとサーバーの間を行き来しているため、遅くなります。 (これはクライアントとサーバーの間ほど悪くはありませんが、それでも余分な作業です。)

オプション2は、tmpテーブルとサブクエリのために遅くなります。

オプション3は次のようなものです

_UPDATE   table2
    JOIN table1  ON table1.id = table2.id
    SET   table2.column = 0
    WHERE table1.column = 0;
_

idは各テーブルの_PRIMARY KEY_であると思いますか?)

重要:_table1_にはINDEX(column)が必要です。

オンラインリファレンスマニュアルの「マルチテーブル更新」をご覧ください。

3
Rick James