简体   繁体   English

在Self上使用IN子查询优化Update查询

[英]Optimize an Update query using IN subquery on Self

I have a 80000 row database with a result number between 130000000 and 168000000, the results are paired using field pid. 我有一个80000行数据库,结果编号在130000000和168000000之间,结果使用字段pid配对。 I need to change the status of the rows from 'G' to 'X' where the result pair has a difference of 4300000. 我需要将行的状态从“ G”更改为“ X”,结果对之间的差值为4300000。

I have come up with the query below, which works but is very slow, can it be improved for speed? 我想出了下面的查询,该查询可以运行,但是速度很慢,可以提高速度吗?

UPDATE table1 SET status = 'X'
WHERE id IN (
SELECT id FROM (
    SELECT a.id AS id FROM table1 a, table1 b
    WHERE a.result = b.result + 4300000
    AND a.pid = b.pid
    AND a.result between 130000000 and 168000000
    AND a.status = 'G'
    ) AS c
);

The indexes are:- 索引是:-

table1  0   PRIMARY 1   id  A   80233   NULL    NULL        BTREE
table1  1   id  1       id  A   80233   NULL    NULL        BTREE
table1  1   id  2   result  A   80233   NULL    NULL        BTREE
table1  1   id  3   status  A   80233   4   NULL    YES BTREE
table1  1   id  4   name    A   80233   32  NULL        BTREE
table1  1   id  5    pid    A   80233   16  NULL        BTREE

Using a subquery inside the IN(..) clause is generally inefficient in MySQL. 在MySQL中,在IN(..)子句中使用子查询通常效率不高。 Instead, you can rewrite the Update query utilizing UPDATE .. JOIN syntax and utilize "self-join" as well: 相反,您可以使用UPDATE .. JOIN语法重写Update查询,也可以使用“自我UPDATE .. JOIN ”:

UPDATE table1 AS a 
JOIN table1 AS b 
  ON b.pid = a.pid 
     AND b.result = a.result - 4300000 
SET a.status = 'X'
WHERE a.result between 130000000 and 168000000 
  AND a.status = 'G'

For good performance (and if I understand NLJ (Nested-Loop-Join) correctly), you would need two indexes: (status,result) and (pid) . 为了获得良好的性能(如果我正确理解NLJ(嵌套循环连接) ),则需要两个索引: (status,result)(pid)

First (composite) index will be used to consider rows from the table alias a . 第一个(复合)索引将用于考虑表别名a行。 Since we have range condition on result , it will be better to define status first, otherwise MySQL would simply stop at the result field in the index (if defined first), due to range condition. 由于我们对result具有范围条件, result最好先定义status ,否则,由于范围条件,MySQL只会在索引的result字段(如果先定义)处停止。

Second index will be used for lookups in the Joined table alias b , using NLJ algorithm . 使用NLJ算法 ,第二个索引将用于Joined表别名b中的查找。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM