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

标签 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
)

我需要更新(设置reservation=1)“store”表(非常大)中的所有行,其中当前reservation=0,但它的id存在于另一个表“item”中。表“item”也很大,但没有“store”那么大。

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

感谢您的任何想法。

最佳答案

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

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,并对其进行解释。 MySQL 5.6 确实支持 UPDATE 语句上的 EXPLAIN。

关于mysql - 优化包含 EXISTS 的 MySQL UPDATE 查询的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29477760/

相关文章:

php - mysql 列的总和

MySQL 多列与单列的速度/优化

sql - 用一个查询替换多个字段

mysql - 将 int-timestamp 转换为时间戳(同时更新行)

php - MySQL 查询仅生成负日差异

php - 使用 GROUP SEPARATOR 的 Explode() 函数

php - 我的个人资料页面,更新详细信息 PHP MYSQL,验证唯一性逻辑

sql-server-2008 - T-SQL 查看子查询Where 子句

postgresql - 返回具有最新时间戳的唯一分组行

mysql - 使用嵌套子查询优化 mysql 查询