4

行の update_dateが条件を満たす場所'A'からテーブルのフラグをリセットする必要があります。'X''Y'1. update_date > 1 month, 2. flag = 'X' & 3. type = 1

そして update_date は別のテーブルに対してチェックされます'B'。次のクエリで、必要なものが正確に説明されることを願っています。また、このクエリは私にとってはうまくいきます。しかし、問題は時間がかかりすぎることです。実際、私のテーブルA & Bははるかに大きく、ほぼ10億行が含まれており、約10列あります。

選択のためにサブクエリを実行するA.idと、すぐに結果が得られました。

 SELECT a.id 
 FROM A a 
 JOIN B b 
 ON (a.id = b.id 
       AND a.name = b.name 
       AND a.type = 1 
       AND a.flag = 'X' 
       AND a.update_date > DATE_SUB(NOW(), INTERVAL 1 MONTH) tmp_table)

しかし、制限を入れても更新クエリだけでも時間がかかります。

UPDATE A 
SET flag='Y' 
WHERE id IN (SELECT a.id 
             FROM A a 
             JOIN B b 
             ON (a.id = b.id 
                   AND a.name = b.name 
                   AND a.type = 1 
                   AND a.flag = 'X' 
                   AND a.update_date > DATE_SUB(NOW(), INTERVAL 1 MONTH) tmp_table))  
             LIMIT 100

クエリを高速化する代替ソリューションを探しています。そのためのストアドプロシージャを作成できることを願っています。しかし、SP各 target_ids ごとにループする必要がありますか?

PHP で 2 つの個別のクエリを記述したくありません。同じ結果 (時間の待ち時間) を返す cron で実行されている PHP スクリプトのスレッドが多数あるためです。

また、列に十分なインデックスを作成していることにも注意してください。

制限ごとに制限を更新したい。つまり、実行ごとに 1000 以上のレコードを更新します。

4

3 に答える 3

3

存在する変更

EXISTS は、エンジンがヒットを検出すると、条件が true であることが証明されると検索を終了するため、高速になります。IN を使用すると、さらに処理する前に、サブクエリからすべての結果を収集します。

UPDATE A a
JOIN B b 
ON (a.id = b.id 
               AND a.name = b.name 
               AND a.type = 1 
               AND a.flag = 'X' 
               AND a.update_date > DATE_SUB(NOW(), INTERVAL 1 MONTH))
SET a.flag='Y'
ORDER BY a.id LIMIT 1000;

EDITED LIMIT のサポート代替 (IT は最初の 100 レコードのみを更新します)

SET @rn = 0;
UPDATE A a
JOIN (SELECT @rn:=@rn+1 AS rId, id, name FROM B b 
      JOIN A a 
      ON (@rn < 100 AND a.id = b.id 
               AND a.name = b.name 
               AND a.type = 1 
               AND a.flag = 'X' 
               AND a.update_date > DATE_SUB(NOW(), INTERVAL 1 MONTH)
      ) 

) b 
ON (a.id=b.id) 
SET a.flag='Y'
WHERE b.rId < 100;

存在句の使用

Update A a 
SET a.flag='Y'
WHERE EXISTS (SELECT 1 FROM B b WHERE a.id = b.id 
               AND a.name = b.name 
               AND a.type = 1 
               AND a.flag = 'X' 
               AND a.update_date > DATE_SUB(NOW(), INTERVAL 1 MONTH)) 
ORDER BY a.id LIMIT 1000;

お役に立てれば

于 2013-03-06T11:45:39.313 に答える
0

最後に、最適化されたクエリのパフォーマンスが向上しました。単に一時テーブルへの結合。

UPDATE A AS a JOIN (
SELECT a.id FROM A AS a JOIN B AS b ON
    b.type = a.type 
    AND b.name = a.name 
    AND b.last_update_date < DATE_SUB(NOW(), INTERVAL 1 MONTH) 
    AND a.type = 1 
    AND a.flag = 'X' 
ORDER BY a.id DESC LIMIT 1000)
AS source ON source.id = a.id
SET flag = 'Y';

http://www.xaprb.com/blog/2006/08/10/how-to-use-order-by-and-limit-on-multi-table-updates-in-mysqlに感謝します

于 2013-03-07T11:48:37.747 に答える