EXPLAIN SELECT select_options
或者
DESCRIBE SELECT select_options
例如:
EXPLAIN SELECT * FROM emp WHERE emp.emp_id = 5
EXPLAIN SELECT * FROM table1 UNION SELECT * FROM table2
表明每个记录所访问的表名,可以是一个表,也可以是多个表。如果需要访问多个表,那就会产生多个记录。
每一个id都对应着不同的查询。对于连接查询来说,一个SELECT关键字后边的FROM字句中可以跟随多个表,所以在连接查询的执行计划中,每个表都会对应一条记录,但是这些记录的id值都是相同的。对于包含子查询的查询语句来说,就可能涉及多个SELECT关键字,所以在包含子查询的查询语句的执行计划中,每个SELECT关键字都会对应一个唯一的id值,
查询语句中不包含UNION或者子查询的查询都算作是SIMPLE类型
对于包含UNION、UNION ALL或者子查询的大查询来说,它是由几个小查询组成的,一般来说,其中最左边的那个查询的select_type的值就是PRIMARY
对于包含UNION或者UNION ALL的大查询来说,它是由几个小查询组成的,其中除了最左边的那个小查询意外,其余的小查询的select_type值就是UNION,可以与PRIMARY对比
MySQL 选择使用临时表来完成UNION查询的去重工作,针对该临时表的查询的select_type就是UNION RESULT
如果包含子查询的查询语句不能够被查询优化器转为对应的多表连接查询的形式,并且该子查询是不相关子查询,并且查询优化器决定采用将该子查询物化的方案来执行该子查询时,该子查询的第一个SELECT关键字代表的那个查询的select_type就是SUBQUERY
物化:不直接将不相关子查询的结果集当作外层查询的参数,而是将该结果集写入一个临时表里
如果包含子查询的查询语句不能够被查询优化器转为对应的多表连接查询的形式,并且该子查询是相关子查询,该子查询的第一个SELECT关键字代表的那个查询的select_type就是DEPENDENT SUBQUERY
UNION操作中,内层的SELECT语句与外层的SELECT语句有依赖关系,则该内层的子查询的select_type就是DEPENDENT UNION
被驱动的SELECT子查询,用来表示包含在FROM子句的子查询中的SELECT(MySQL会递归执行并将结果放到一个临时表中,MySQL内部将其称为是Derived table派生表),也就是说位于FROM子句中的子查询的select_type就是DERIVED
被物化的子查询,也就是说当查询优化器在执行包含子查询的语句时,选择将子查询物化之后的外层查询进行连接查询时,该子查询对应的select_type属性就是MATERIALIZED
结果值从最好到最坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
当表中只有一条记录并且该表使用的存储引擎的统计数据是精确的。比如MyISAM、Memory,那么对一个表的count(*)的访问方法就是system,因为其保存了每个表中数据的数量多少,不需遍历计数。而InnoDB需要现场统计数量,因此就不是system
当我们根据主键或者唯一二级索引列与常数进行等值匹配时,对单表的访问方法就是const
在连接查询时,如果被驱动表是通过主键或者唯一二级索引列等值匹配的方式进行访问的(如果该主键或者唯一二级索引是联合索引的话,所有的索引列都必须进行等值比较)。则对该被驱动表的访问方法就是eq_ref
当通过普通的二级索引列与常量进行等值匹配时来查询某个表,那么对该表的访问方法就可能是ref
对普通二级索引进行等值匹配查询,该索引列的值也可以是NULL值时,那么对该表的访问方法就可能是ref_or_null
一般情况下对于某个表的查询只能使用到一个索引,但单表访问方法时在某些场景下可以使用Interseation、union、Sort-Union这三种索引合并的方式来执行查询。
类似于两表连接中被驱动表的eq_ref访问方法,unique_subquery是针对在一些包含IN子查询的查询语句中,如果查询优化器决定将IN子查询转换为EXISTS子查询,而且子查询可以使用到主键进行等值匹配的话,那么该子查询执行计划的type列的值就是unique_subquery
index_subquery与 unique_subquery类似,只不过访问子查询中的表时使用的是普通的索引
如果查询优化器不决定将IN子查询转换为EXISTS子查询,那么该子查询执行计划的type列的值就是range
当我们可以使用索引覆盖,但需要扫描全部的索引记录时,该表的访问方法就是index
全表扫描
在EXPLAIN语句输出的执行计划中,possible_keys列表示在某个查询语句中,对某个列执行单表查询时可能用到的索引有哪些。一般查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用。key列表示实际用到的索引有哪些,如果为NULL,则没有使用索引
实际使用到的索引长度 (即:字节数),可以帮我们检查是否充分的利用了索引,值越大越好,主要针对于联合索引,有一定的参考意义
预估的需要读取的记录条数,值越小越好
某个表经过搜索条件过滤后剩余记录条数的百分比,我们更关注在连接查询中驱动表对应的执行计划记录的filtered值,它决定了被驱动表要执行的次数 (即: rows * filtered)
Extra列是用来说明一些额外信息的,包含不适合在其他列中显示但十分重要的额外信息。我们可以通过这些额外信息来更准确的理解MySQL到底将如何执行给定的查询语句
当查询语句没有FROM子句时将会提示该额外信息
当查询语句的WHERE子句永远为FALSE时将会提示该额外信息
当查询列表处有MIN或者MAX聚合函数,但是并没有符合WHERE子句中的搜索条件的记录
当我们的查询列表以及搜索条件中只包含属于某个索引的列,也就是在可以使用覆盖索引的情况下,在Extra列将会提示该额外信息。
有些搜索条件中虽然出现了索引列,但却不能使用到索引
在连接查询执行过程中,当被驱动表不能有效的利用索引加快访问速度,MySQL一般会为其分配一块名叫join buffer的内存块来加快查询速度
当我们使用左(外)连接时,如果WHERE子句中包含要求被驱动表的某个列等于NULL值的搜索条件,而且那个列是不允许存储NULL值的,那么在该表的执行计划的Extra列就会提示这个信息
如果执行计划的Extra列出现了Using intersect(…)提示,说明准备使用Intersect索引合并的方式执行查询,括号中的…表示需要进行索引合并的索引名称
如果出现Using union(…)提示,说明准备使用Union索引合并的方式执行查询
如果出现Using sort_union(…)提示,说明准备使用Sort-Union索引合并的方式执行查询
当我们的LIMIT子句的参数为0时,将会提示该额外信息
说明此时排序的执行方式为文件排序。如果查询中需要使用filesort的方式进行排序的记录非常多,那么这个过程是很耗费性能的,我们最好想办法将使用文件排序的执行方式改为索引进行排序
说明在执行查询操作时,需要建立临时表。执行计划中出现Using temporary并不是一个好的征兆,因为建立与维护临时表要付出很大的成本的,所以我们最好能使用索引来替代掉使用临时表
传统格式简单明了,输出是一个表格形式,概要说明查询计划
EXPLAIN SELECT ....
传统格式中介绍的EXPLAIN语句输出中缺少了一个衡量执行好坏的重要属性 —— 成本。而JSON格式是四种格式里面输出信息最详尽的格式,里面包含了执行的成本信息
EXPLAIN FORMAT=JSON SELECT ....
TREE格式是8.0.16版本之后引入的新格式,主要根据查询的 各个部分之间的关系和各部分的执行顺序来描述如何查询
EXPLAIN FORMAT=TREE SELECT ....
可以通过MySQL Workbench可视化查看MySQL的执行计划