Explain命令是查看查询优化器是如何决定执行查询的主要方法。这个功能有局限性,并不总会说出真相,但它的输出是可以获取的最好信息,值得花时间去了解,因为可以学习到查询是如何执行的。学会解释explain将会帮助你了解MySQL优化器是如何工作的。

先上官方文档表格:

列字段

含义

id

查询序号

select_type

查询类型

table

表名

type

join类型

partitions

匹配的分区

possible_keys

可能选择的索引

key

实际选择的索引

key_len

索引长度

ref

与索引作比较的列

rows

大概需要检索的行数

filtered

按表条件过滤的行百分比

Extra

附加信息

1.id

这一列总是包含一个编号,标识select所属的行。如果在语句当中没有子查询活联合查询,那么就只会有唯一的select,于是每一行在这个列中都将显示一个1。否则,内层的select语句一般会顺序编号,对应于其在原始语句的位置。

2.select_type

查询的类型,可以是下表的任何一种类型:

select_type

字段说明

select_type

类型说明

SIMPLE

简单SELECT(不使用UNION或子查询)

PRIMARY

最外层的SELECT

UNION

UNION中第二个或之后的SELECT语句

DEPENDENT UNION

UNION中第二个或之后的SELECT语句取决于外面的查询

UNION RESULT

UNION的结果

SUBQUERY

子查询中的第一个SELECT

DEPENDENT SUBQUERY

子查询中的第一个SELECT, 取决于外面的查询

DERIVED

衍生表(FROM子句中的子查询)

MATERIALIZED

物化子查询

UNCACHEABLE SUBQUERY

结果集无法缓存的子查询,必须重新评估外部查询的每一行

UNCACHEABLE UNION

UNION中第二个或之后的SELECT,属于无法缓存的子查询

3.table

显示这一步所访问的数据库中的表的名称。

4.type(重要)

这是最重要的字段之一,显示查询使用了何种类型。从最好到最差的连接类型依次为:

system,const,eq_ref,ref,fulltext,ref_or_null,index_merge,unique_subquery,index_subquery,range,index,ALL
除了all之外,其他的type都可以使用到索引,除了index_merge之外,其他的type只可以用到一个索引。

1、system

表中只有一行数据或者是空表,这是const类型的一个特例。且只能用于myisam和memory表。如果是Innodb引擎表,type列在这个情况通常都是all或者index

2、const

最多只有一行记录匹配。当联合主键或唯一索引的所有字段跟常量值比较时,join类型为const。其他数据库也叫做唯一索引扫描

3、eq_ref

多表join时,对于来自前面表的每一行,在当前表中只能找到一行。这可能是除了system和const之外最好的类型。当主键或唯一非NULL索引的所有字段都被用作join联接时会使用此类型。

eq_ref可用于使用’='操作符作比较的索引列。比较的值可以是常量,也可以是使用在此表之前读取的表的列的表达式。

相对于下面的ref区别就是它使用的唯一索引,即主键或唯一索引,而ref使用的是非唯一索引或者普通索引。
eq_ref只能找到一行,而ref能找到多行。

4、ref

对于来自前面表的每一行,在此表的索引中可以匹配到多行。若联接只用到索引的最左前缀或索引不是主键或唯一索引时,使用ref类型(也就是说,此联接能够匹配多行记录)。

ref可用于使用’=‘或’<=>'操作符作比较的索引列。

5、 fulltext

使用全文索引的时候是这个类型。要注意,全文索引的优先级很高,若全文索引和普通索引同时存在时,mysql不管代价,优先选择使用全文索引

6、ref_or_null

跟ref类型类似,只是增加了null值的比较。实际用的不多。

SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;

7、index_merge

表示查询使用了两个以上的索引,最后取交集或者并集,常见and
,or的条件使用了不同的索引,官方排序这个在ref_or_null之后,但是实际上由于要读取多个索引,性能可能大部分时间都不如range

8、unique_subquery

用于where中的in形式子查询,子查询返回不重复值唯一值,可以完全替换子查询,效率更高。 该类型替换了下面形式的IN子查询的ref:
value IN (SELECT primary_key FROM single_table WHERE some_expr)

9、index_subquery

该联接类型类似于unique_subquery。适用于非唯一索引,可以返回重复值。

10、range

索引范围查询,常见于使用 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN,
IN()或者like等运算符的查询中。

SELECT * FROM tbl_name WHERE key_column = 10;

SELECT * FROM tbl_name WHERE key_column BETWEEN 10 and 20;

SELECT * FROM tbl_name WHERE key_column IN (10,20,30);

11、index

索引全表扫描,把索引从头到尾扫一遍。这里包含两种情况:
一种是查询使用了覆盖索引,那么它只需要扫描索引就可以获得数据,这个效率要比全表扫描要快,因为索引通常比数据表小,而且还能避免二次查询。
在extra中显示Using index,反之,如果在索引上进行全表扫描,没有Using index的提示。

12、all
全表扫描,性能最差。

5.possible_keys

该列显示的为分区表命中的分区情况。非分区表该字段为空(null)。

6.possible_keys

查询可能使用到的索引都会在这里列出来。

7. key

查询真正使用到的索引。
select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个。

8.key_len

查询用到的索引长度(字节数)。
如果是单列索引,那就整个索引长度算进去,如果是多列索引,那么查询不一定都能使用到所有的列,用多少算多少。留意下这个列的值,算一下你的多列索引总长度就知道有没有使用到所有的列了。

key_len只计算where条件用到的索引长度,而排序和分组就算用到了索引,也不会计算到key_len中。

9. ref

如果是使用的常数等值查询,这里会显示const,如果是连接查询,被驱动表的执行计划这里会显示驱动表的关联字段,如果是条件使用了表达式或者函数,或者条件列发生了内部隐式转换,这里可能显示为func。

10. rows(重要)

rows 也是一个重要的字段。 这是mysql估算的需要扫描的行数(不是精确值)。
这个值非常直观显示 SQL 的效率好坏, 原则上 rows 越少越好。

11. filtered

这个字段表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例,注意是百分比,不是具体记录数。这个字段不重要。

12. Extra(重要)

Explain 中的很多额外的信息会在 Extra 字段显示, 常见的有以下几种内容:

using index : 出现这个说明mysql使用了覆盖索引,避免访问了表的数据行,效率不错。

using where :这说明服务器在存储引擎收到行后讲进行过滤。

using temporary :这意味着mysql对查询结果进行排序的时候使用了一张临时表

using filesort :这个说明mysql会对数据使用一个外部的索引排序

注意当出现using temporary 和 using filesort时候说明需要优化操作。

参考地址:https://dev.mysql.com/doc/refman/5.7/en/explain-output.html#explain_extra