有人可以给我一个关于如何优化这个需要大约一分钟处理的更新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"。
我不是创建高效查询的专家,所以请原谅我,如果这只是一种完全错误的态度,而且整个事情都有一个简单的解决方案。
感谢任何想法。
答案 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
作为前导列的索引。还包括status
和id
列将意味着可以从索引页面检查这些条件,而无需查找表中的基础页面。
对于相关子查询(依赖查询),我们希望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'表。