根据Sasha Pachev的《理解MySQL内部原理》一书的第9章(解析器和优化器)的第172页
以下是按以下任务对查询的评估的细分:
- 确定哪些键可用于从表中检索记录,然后为每个表选择最佳键。
- 对于每个表,确定表扫描是否比键读取更好。如果有很多与键值匹配的记录,则键的优点会降低,并且表扫描会变得更快。
- 确定查询中存在多个表时,应联接表的顺序。
- 重写WHERE子句以消除无效代码,减少不必要的计算,并在可能的情况下更改约束,以打开使用键的方式。
- 从联接中删除未使用的表。
- 确定是否可以将键用于
ORDER BY
和GROUP BY
。
- 尝试简化子查询,并确定可以将其结果缓存到什么程度。
- 合并视图(将视图引用扩展为宏)
在同一页面上,它显示以下内容:
在MySQL优化程序术语中,每个查询都是一组联接。术语“ 连接”在这里比在SQL命令中使用得更广泛。仅对一个表的查询是简并联接。虽然我们通常不认为从一个表中读取记录是一个联接,但是与常规联接相同的结构和算法可以完美地解决仅一个表的查询问题。
结语
由于存在键,数据量和查询的表达式,MySQL Joins有时可能会为我们自己(或找回我们)做些事情,并得出我们没想到且无法快速解释的结果。
我以前写过关于这个古怪的东西
因为MySQL Query Optimizer可以在查询评估期间关闭某些键。
@Phil的评论帮助我看看如何发布此答案(@Phil的评论+1)
@ypercube的评论(也是该评论的+1)是我的帖子的紧凑版本,因为MySQL的查询优化器是原始的。不幸的是,它必须是因为它处理外部存储引擎。
结论
至于您的实际问题,MySQL查询优化器将确定每个查询完成后的性能指标
- 计数行
- 选择键
- 按摩间歇结果集
- 哦,是的,进行实际的JOIN
您可能必须通过重写(重构)查询来强制执行顺序
这是您给的第一个查询
select count(*)
from table1 a
join table2 b
on b.key_col=a.key_col
where b.tag = 'Y';
尝试重写它以首先评估WHERE
select count(*)
from table1 a
join (select key_col from table2 where tag='Y') b
on b.key_col=a.key_col;
那肯定会改变EXPLAIN计划。它可能产生更好或更差的结果。
我曾经在StackOverflow中回答了一个应用此技术的问题。解释是可怕的,但表现是炸药。之所以起作用,是因为存在正确的索引,并且在子查询中使用了LIMIT。
与股票价格一样,当涉及到查询并试图表达它们时,也会受到限制,结果可能会有所不同,并且过去的表现并不代表未来的结果。