Explain是一个非常有的命令,可以用来获取关于查询执行计划的信息,以及如何解释输出。Explain命令是查看查询优化器如何决定执行查询的主要方法。这个功能有一定的局限性,并不总是会说出真相,但是它的输出是可以获取的最好信息,值得花时间了解,可以学习到查询是如何执行的。
调用Explain
要使用Explain,只需在查询中的select关键字之前增加Explain这个词。MySQL会在查询上设置一个标记。当执行查询时,这个标记会使其返回关于在执行计划中每一步的信息,而不是执行它。
我们来简单看一下例子:可能是最简单的Explain结果
在查询中每个表在输出中只有一行。如果查询是两个表的联接,那么输出中将有两行。别名表单算为一个表。
Explain有两个主要的变种
Explain extended看起来和正常的explain行为一样,但它会告诉服务器“逆向编译”执行计划为一个select语句。可以通过紧接其后运行showwarnings看到这个生成的语句。这个语句直接来自执行计划,而不是原SQL语句,到这点上已经变成一个数据结构。大部分场景下,它都是优化过的,跟原语句不相同,可以学习查询优化器到底是如何转化语句的。
Explain partitions会显示查询将访问的分区,如果查询是基于分区表的话。
一般认为增加explain时,MySQL语句不会执行查询,这是错误的。如果查询在from子句中包括子查询,那么MySQL实际上是会执行子查询,将其结果放在一个临时表中,然后完成外层查询优化。
前面简单解释了一下Explain可以做到的事情,但是Explain也有自身的一些限制:
Explain根本不会告诉你触发器,存储过程或者UFD会如何影响查询。
它不支持存储过程,尽管可以手动抽取查询并单独地对其进行explain操作。
它并不会告诉你MySQL在查询执行中所做的特定优化。
它并不会显示关于查询的执行计划的所有信息。
它并不区分具有相同名字的事物。比如,对内存排序和临时文件都用“filesort”,对磁盘上和内存中的临时表都显示“Using temporary”。
可能会误导。比如,会对一个有着很小的LIMIT的查询显示全索引扫描。
重写非select查询
MySQL Explain只能解释select查询,并不会对存储过程调用和insert,update,delete或其他语句做解释。但是,我们可以重写这些非select语句来利用explain。为了利用explain,我们需要将这些语句转化成一个等价的访问所有相同列的select,所有需要的列必须在select列表,关联子句,或者where子句中。
Explain中的列