2014-10-12 107 views
1

我有两个提供相同输出的SQL查询。 我的第一直觉是使用这样的:两个类似SQL查询之间的巨大性能差异

SELECT * FROM performance_dev.report_golden_results 
where id IN (SELECT max(id) as 'id' from performance_dev.report_golden_results 
group by platform_id, release_id, configuration_id) 

现在,这把像70秒即可完成!

搜索另一种解决办法我试过类似的东西:

SELECT * FROM performance_dev.report_golden_results e 
join (SELECT max(id) as 'id' 
from performance_dev.report_golden_results 
group by platform_id, release_id, configuration_id) s 
ON s.id = e.id; 

出人意料的是,这场耗时0.05秒即可完成!

这两个怎么这么不同?

谢谢!

+2

'''''''''''''''''''''''这就是为什么使用明确的“join”编写这样的查询通常更好。 – 2014-10-12 08:59:30

+0

从我记得,MySql无法正确优化子查询,但您的第二个查询使用连接。您需要检查执行计划才能正确看到它正在执行的操作 – ydaetskcoR 2014-10-12 09:01:06

+2

查看两个查询的'EXPLAIN'输出。 – Barmar 2014-10-12 09:02:34

回答

0

这可能会导致的时滞第一件事就是MySQL使用“半连接”战略Subqueries.The半加入,包括以下步骤:

如果一个子查询符合上述标准时,MySQL将其转换为一个 半联接,使一个基于成本的选择从这些策略:

转换子查询为连接,或者使用表拉出并运行该查询 作为内子查询表和外表之间的连接。表 拉出从子查询拉出一个表到外部查询。

Duplicate Weedout:运行半连接,就好像它是连接一样,并使用临时表删除 重复记录。 FirstMatch:当扫描行组合的内表和 时,有多个给定值组的实例,选择一个而不是全部返回它们。这种“快捷方式”扫描并消除了不必要的行的产生。

LooseScan:使用索引扫描子查询表,该索引可以从每个子查询的值组中选择一个 值。

将子查询物化为包含索引的临时表,并使用 临时表执行连接。该索引用于删除 重复项。当 将临时表与外部表连接在一起时,该索引稍后也可用于查找;如果不是,则扫描表 。

但给予明确的加入会减少这些可能是原因的努力。

我希望它有帮助!