优化包含EXISTS的MySQL UPDATE查询的性能

时间:2015-04-06 19:00:47

标签: mysql sql-update subquery query-optimization exists

有人可以给我一个关于如何优化这个需要大约一分钟处理的更新MySQL查询的提示吗?

UPDATE store s 
SET reservation=1 
WHERE EXISTS (
  SELECT 1 
  FROM item i 
  WHERE s.reservation=0 
    AND s.status!=9 
    AND s.id=i.store_id 
    AND i.store_id!=0
)

我需要更新(设置预留= 1)" store"中的所有行table(非常大),其中当前预留= 0但它的id存在于另一个表" item"中。表"项目"也很大,但没有" store"。

我不是创建高效查询的专家,所以请原谅我,如果这只是一种完全错误的态度,而且整个事情都有一个简单的解决方案。

感谢任何想法。

2 个答案:

答案 0 :(得分:0)

看起来相关子查询中的某些谓词可以移动到外部查询。例如,我认为这是等价的:

UPDATE store s 
   SET s.reservation = 1
 WHERE s.reservation = 0
   AND s.status != 9
   AND s.id != 0
   AND EXISTS ( SELECT 1
                  FROM item i
                 WHERE i.store_id = s.id
              )

为了获得最佳效果,我们至少要求store上有reservation作为前导列的索引。还包括statusid列将意味着可以从索引页面检查这些条件,而无需查找表中的基础页面。

对于相关子查询(依赖查询),我们希望item上的索引以store_id作为前导列。

作为另一种选择,请考虑将相关子查询重写为JOIN操作,例如:

UPDATE store s
  JOIN item i
    ON i.store_id = s.id
   SET s.reservation = 1
 WHERE s.reservation = 0
   AND s.status != 9
   AND s.id != 0

如果您运行的是MySQL 5.5或更早版本,则无法在UPDATE语句中获取EXPLAIN。我们可以得到的最接近的是将查询重写为SELECT,并获得一个EXPLAIN。 MySQL 5.6在UPDATE语句中支持EXPLAIN。

答案 1 :(得分:0)

您可以尝试使用:

UPDATE store s INNER JOIN item i ON s.id=i.store_id SET reservation=1 WHERE i.store_id!=0 AND s.reservation=0 AND s.status != 9;

这种情况应该更快,因为每当你需要检查'store'行时,你不会通过所有'item'表。