我有两个提供相同输出的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秒才能完成!!!
为什么这两者如此不同?
谢谢!
答案 0 :(得分:0)
可能导致时间滞后的第一件事是MySQL使用“半连接”策略进行子查询。半连接包括以下步骤:
如果子查询符合上述条件,MySQL会将其转换为a 半连接并根据这些策略进行基于成本的选择:
将子查询转换为连接,或使用表pullout并运行查询 作为子查询表和外部表之间的内部联接。表 pullout将一个表从子查询拉出到外部查询。
Duplicate Weedout:运行半连接,就好像它是一个连接并删除 使用临时表重复记录。
FirstMatch:扫描内部表格中的行组合和 有一个给定值组的多个实例,请选择一个 而不是归还他们。这种“快捷方式”扫描并消除 产生不必要的行。
LooseScan:使用启用单个索引的索引扫描子查询表 要从每个子查询的值组中选择的值。
将子查询实现为具有索引和使用的临时表 用于执行连接的临时表。该索引用于删除 重复。索引也可能稍后用于查找 将临时表与外表联系起来;如果没有,表格 扫描。
但是,明确加入会减少这些可能是原因的努力。
我希望它有所帮助!
答案 1 :(得分:0)
MySQL 不考虑第一个查询作为半连接优化的主题(MySQL 通过某种优化将半连接转换为经典连接:第一次匹配,重复淘汰......) 因此,将对第一个表进行全面扫描,并对外部选择生成的每一行评估子查询:因此性能不佳。
第二个是经典连接,在这种情况下会发生什么,MySQL 将计算派生查询的结果,然后仅将来自该查询的值与满足条件的第一个查询的值进行匹配,因此不需要完全扫描第一个表(我在这里假设 id 是一个索引列)。
现在的问题是为什么 MySQL 不考虑将第一个查询作为半连接优化的主题:答案记录在 MySQL https://dev.mysql.com/doc/refman/5.6/en/semijoins.html
In MySQL, a subquery must satisfy these criteria to be handled as a semijoin:
It must be an IN (or =ANY) subquery that appears at the top level of the WHERE or ON clause, possibly as a term in an AND expression. For example:
SELECT ...
FROM ot1, ...
WHERE (oe1, ...) IN (SELECT ie1, ... FROM it1, ... WHERE ...);
Here, ot_i and it_i represent tables in the outer and inner parts of the query, and oe_i and ie_i represent expressions that refer to columns in the outer and inner tables.
It must be a single SELECT without UNION constructs.
It must not contain a GROUP BY or HAVING clause.
It must not be implicitly grouped (it must contain no aggregate functions).
It must not have ORDER BY with LIMIT.
The STRAIGHT_JOIN modifier must not be present.
The number of outer and inner tables together must be less than the maximum number of tables permitted in a join.
您的子查询使用 GROUP BY,因此未应用半连接优化。