2015-04-06 89 views
0

任何人都可以给我一个关于如何优化此更新的提示MySQL查询需要大约一分钟的时间来处理?优化包含EXISTS的MySQL UPDATE查询的性能

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),在“商店”表中的所有行(这是非常大),那里是目前预订= 0,但它在另一个表“项目”存在的ID。表“项目”也很大,但不如“存储”。

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

感谢您的任何想法。

回答

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 
      ) 

对于最能表现,至少,我们会希望有reservation作为前导列上store的索引。还包括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。

+0

感谢您的全面解答 - 将子查询重写为JOIN实际执行速度要快得多 - 而不是几分钟就花了几秒钟!添加索引对于未来的操作将更加有效。 – Johnny

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; 

这种情况,因为当你需要检查“存储”行,你不会每次都去通所有的“项目”表应工作得更快。

+0

谢谢!此查询执行的速度比使用存在的要快得多。 – Johnny