官方参考文档:https://dev.mysql.com/doc/refman/8.0/en/explain-output.html

  1. 表的执行顺序
  2. 数据读取操作的操作类型
  3. 哪些索引被使用
  4. 哪些索引被实际使用
  5. 表之间的引用
  6. 每张表有多少行被优化器查询

    查看Explain字段

    1. mysql> EXPLAIN SELECT 1;
    2. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+
    3. | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
    4. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+
    5. | 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
    6. +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------+
    7. 1 row in set, 1 warning (0.01 sec)
    | Column | JSON Name | Meaning | 描述 | | —- | —- | —- | —- | | id | select_id | The SELECT identifier | 选择标识符 | | select_type | None | The SELECT type | 表示查询的类型 | | table | table_name | The table for the output row | 输出行的表 | | partitions | partitions | The matching partitions | 匹配的分区 | | type | access_type | The join type | 表示表的连接类型 | | possible_keys | possible_keys | The possible indexes to choose | 表示查询时,可能使用的索引 | | key | key | The index actually chosen | 表示实际使用的索引 | | key_len | key_length | The length of the chosen key | 索引字段的长度 | | ref | ref | The columns compared to the index | 与索引比较的列 | | rows | rows | Estimate of rows to be examined | 扫描出的行数(估算的行数) | | filtered | filtered | Percentage of rows filtered by table condition | 按表条件过滤的行百分比 | | Extra | None | Additional information | 附件信息 |

id列

id 列的编号是 select 的序列号,有几个 select 就有几个 id,并且 id 的顺序是按 select 出现的顺序增长的。
id 列越大执行优先级越高,id 相同则从上往下执行,id 为 NULL 最后执行。

select_type列

select_type Value JSON Name Meaning 描述
SIMPLE None Simple SELECT
(not using UNION
or subqueries)
简单Select查询,不使用 union 或者子查询
PRIMARY None Outermost SELECT 最外层查询
UNION None Second or later SELECT
statement in a UNION
UNION中的第二个或后面的SELECT语句
DEPENDENT UNION dependent (true) Second or later SELECT
statement in a UNION
, dependent on outer query
UNION中的第二个或后面的SELECT语句,取决于外面的查询
UNION RESULT union_result Result of a UNION UNION的结果
SUBQUERY None First SELECT
in subquery
子查询中的第一个SELECT,结果不依赖于外部查询
DEPENDENT SUBQUERY dependent (true) First SELECT
in subquery, dependent on outer query
子查询中的第一个SELECT,依赖于外部查询
DERIVED None Derived table 派生表
DEPENDENT DERIVED dependent (true) Derived table dependent on another table 派生表依赖于另一个表
MATERIALIZED materialized_from_subquery Materialized subquery
UNCACHEABLE SUBQUERY cacheable (false) A subquery for which the result cannot be cached and must be re-evaluated for each row of the outer query 无法缓存结果并且必须为外部查询的每一行重新评估的子查询
UNCACHEABLE UNION cacheable (false) The second or later select in a UNION
that belongs to an uncacheable subquery (see UNCACHEABLE SUBQUERY)

table列

表示正在访问的哪张表
显示这一步所访问数据库中表名称(显示这一行的数据是关于哪张表的),有时不是真实的表名字,可能是简称,例如上面的e,d,也可能是第几步执行的结果的简称。

partitions列

查询将匹配记录的分区。该值NULL用于非分区表。

type列

type 表示联接类型

联接类型 描述
system 该表只有一行(系统表),特殊的 const
const 该表最多有一个匹配行,在查询开始时读取。因为只有一行,该行中该列的值可以被优化器的其余部分视为常量。
eq_ref 对于前面表中的每个行组合,从该表中读取一行。除了 systemand const类型之外,这是最好的连接类型。当连接使用索引的所有部分并且索引是一个 PRIMARY KEY或UNIQUE NOT NULL索引时使用它。
ref 对于先前表中的每个行组合,从该表中读取具有匹配索引值的所有行。ref如果联接仅使用键的最左前缀或键不是 aPRIMARY KEY或 UNIQUE索引(换句话说,如果联接无法根据键值选择单行),则使用。如果使用的键只匹配几行,这是一个很好的连接类型。
fulltext 连接是使用FULLTEXT 索引执行的。
ref_or_null 这种连接类型类似于 ref,但另外,MySQL 会额外搜索包含NULL值的行。这种连接类型优化最常用于解析子查询。
index_merge 此连接类型表示使用了索引合并优化。在这种情况下,key输出行中的列包含所使用索引的列表,并key_len包含所使用索引 的最长关键部分的列表。
unique_subquery unique_subquery 只是一个索引查找函数,完全替换子查询以提高效率。
index_subquery
range
index 该index联接类型是一样的 ALL,只是索引树被扫描
ALL 对先前表中的每个行组合进行全表扫描

possible_keys 列

指出 MySQL 能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用(该查询可以利用的索引,如果没有任何索引显示 null)

key 列

key 列显示 MySQL 实际决定使用的键(索引),必然包含在 possible_keys 中

key_len列

表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的)

ref 列

列与索引的比较,表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值。

rows 列

估算出结果集行数,表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数

filtered 列

该 filtered 列指示按表条件过滤的表行的估计百分比。最大值为 100,这意味着没有发生行过滤。从 100 开始减小的值表示过滤量增加。 rows显示估计的检查行数,rows× filtered显示与下表连接的行数。例如,如果 rows是 1000 和 filtered50.00 (50%),则与下表连接的行数为 1000 × 50% = 500。

Filtered表示返回结果的行数占需读取行数的百分比 Filtered列的值越大越好 Filtered列的值依赖于统计信息

Extra 列

顾名思义,Extra列是用来说明一些额外信息的,我们可以通过这些额外信息来更准确的理解MySQL到底将如何执行给定的查询语句。

索引覆盖,就是select的数据列只用从索引中就能够取得,不必读取数据行,MySQL可以利用索引返回select列表中的字段,而不必根据索引再次读取数据文件,换句话说查询列要被所建的索引覆盖。

Extra 说明
Using filesort 说明MySQL会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行排序,MySQL无法利用索引完成的排序称为“文件排序”
Using temporary 使用了临时表保存中间结果,MySQL在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by
USING index 表示相应的select操作中使用了覆盖索引(Covering index),避免访问了表的数据行,效率不错。如果同时出现 using where,标明索引被用来执行索引键值的查找。如果没有同事出现 using where,标明索引用来读取数据而非执行查找动作。
using where 标明使用了where过滤
using join buffer 使用了连接缓存
impossible where where子句的值总是false,不能用来获取任何元组。
select tables optimized away
distinct 优化distinct操作,在找到第一匹配的元组后即停止找同样值得动作

添加索引建议

  1. 永远用小结果集驱动大的结果集;
  2. 索引最好设置在需要经常查询的字段中;
  3. 左连接索引添加在右表上,右连接索引添加在左表上;
  4. 全值匹配我最爱
  5. 最佳左前缀法则
  6. 不在索引列上做任何操作(计算、函数、类型转换),会导致索引失效而转向全表扫码
  7. 存储引擎不能使用索引中范围条件的右边的列(范围查询后,后面的索引失效;)
  8. 尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *
  9. mysql 在使用不等于(!= 或者 <>)的时候无法使用索引会导致全表扫描
  10. is null,is not null 也无法使用索引
  11. like 以通配符开头 mysql 索引失效会变成全表扫描的操作
  12. 字符串不加单引号索引失效
  13. 少用or,用它来连接时索引失效