知识卡片
EXPLAIN只是近似值,不是真相——它甚至会真的执行子查询
内容
EXPLAIN是查看MySQL查询优化器决策的主要窗口,但把它的输出当成”绝对 准确的执行真相”是一个常见的误用。一个反直觉的事实是:给一条语句加上 EXPLAIN,并不意味着MySQL不会真的执行任何东西——如果FROM子句里包含 子查询,MySQL实际上会先执行这个子查询、把结果放进一张临时表,然后 才能继续对外层查询做优化分析,因为在完成外层优化之前必须先拿到子 查询的结果。这意味着对一条包含开销很大的子查询、或者使用临时表算法的 [[临时表算法视图无法下推条件也没有索引]]的语句执行EXPLAIN,实际上会 触发这部分真实的、有代价的工作,而不是一次纯粹”只看不做”的静态分析。 除此之外,EXPLAIN本身还有一系列结构性的局限,需要带着这些局限去 解读它的输出,而不是全盘照单全收:它完全不会告诉你触发器、存储过程 或用户自定义函数会如何影响查询的实际执行;它不区分具体细节相同但 本质不同的东西——比如内存里完成的排序和落到磁盘临时文件的排序, 在Extra列里都统一显示成”filesort”,磁盘上的临时表和内存中的临时表 也都显示”Using temporary”,这意味着看到”filesort”或”Using temporary” 本身不能判断这是轻量操作还是重量级的磁盘I/O;它甚至可能直接给出 误导性的信息,比如早期版本对一个带很小LIMIT的查询也会显示出”全索引 扫描”,而实际执行时因为LIMIT的存在很快就会提前终止扫描。这些局限 说明EXPLAIN应该被当作”优化器决策的一个有用近似”,具体执行细节的 判断还是要结合实际的执行时间、扫描行数这些真实运行数据来交叉验证。
参考来源
- 位置:《高性能MySQL:第3版》附录D"EXPLAIN"(源文件:
_epub-src/OEBPS/Text/part0027.xhtml)
- 结论依据:原文明确"认为增加EXPLAIN时MySQL不会执行查询,这是一个
常见的错误。事实上,如果查询在FROM子句中包括子查询,那么MySQL
实际上会执行子查询……要意识到EXPLAIN只是个近似结果,别无其他……
它并不区分具有相同名字的事物。例如,它对内存排序和临时文件都使用
'filesort'……可能会误导。例如,它会对一个有着很小LIMIT的查询显示
全索引扫描",直接列出EXPLAIN会真实执行子查询及其若干具体局限。
- 原始内容:认为增加EXPLAIN时MySQL不会执行查询,这是一个常见的
错误。事实上,如果查询在FROM子句中包括子查询,那么MySQL实际上
会执行子查询,将其结果放在一个临时表中。