知识卡片

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实际上 会执行子查询,将其结果放在一个临时表中。