通过explain可以返回的执行计划信息,从而使我们可以知道sql具体的计划执行情况,例如查询的行叔叔,索引使用情况等,从而能够优化我们的sql。

在 select 语句之前增加 explain 关键字,MySQL 会在查询上设置一个标记,执行查询时,会返回执行计划的信息,而不是执行这条SQL。

示例:

explain select * from user

上面的语句会返回很多字段,下面一一解读,其中需要重点看的是type、key、rows。

  1. id

MySQL 会为每个 select 语句分配⼀个唯⼀的 id 值。

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

  1. select_type

查询的类型,根据关联、union、⼦查询等等分类,主要有如下几种:

  • simple:简单查询,不包含子查询或union等;
  • primary:复杂查询,最外层的查询。意思就是该查询语句包含子查询等操作,然后最外面的那个最大的select,就称之为复杂查询;
  • subquery:子查询,指在select语句里面的子查询;
  • derived:衍生查询,这个是在from语句后面的查询语句,MySQL会将结果存放在一个临时表中,也称为派生表;
  • UNION:若第二个SELECT出现在UNION之后,则被标记为UNION;若UNION包含在FROM自居的子查询中,外层SELECT被标记为DERIVED;
  • UNION RESULT:从UNION表获取结果的SELECT。
  1. table

表示 explain 的⼀⾏正在访问哪个表。

  1. type

最重要的列之⼀。表示关联类型或访问类型,即 MySQL 决定如何查找表中的⾏。

主要有如下几种类型:

  • system:当表仅有⼀⾏记录时(系统表),数据量很少,往往不需要进⾏磁盘 IO,速度⾮常快。
  • const:表示查询时命中 primary key 主键或者 unique 唯⼀索引,或者被连接的部分是⼀个常量值。这类扫描效率极⾼,返回数据量少,速度⾮常快。
  • eq_ref:primary key 或 unique key 索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录。
  • ref_or_null:这种连接类型类似于 ref,区别在于 MySQL 会额外搜索包含 NULL 值的⾏。
  • index_merge:使⽤了索引合并优化⽅法,查询使⽤了两个以上的索引。
  • unique_subquery:替换下⾯的 IN ⼦查询,⼦查询返回不重复的集合。
  • index_subquery::区别于 unique_subquery ,⽤于⾮唯⼀索引,可以返回重复值。
  • range:使⽤索引选择⾏,仅检索给定范围内的⾏。简单点说就是针对⼀个有索引的字段,给定范围检索数据。在 where 语句中使⽤ bettween…and 、 、 <= 、 in 等条件查询 type 都是 range。
  • index:: Index 与 ALL 其实都是读全表,区别在于 index 是遍历索引树读取,⽽ ALL 是从硬盘中读取。
  • ALL:全表扫描。

性能从最优到最差分别为:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge >

unique_subquery > index_subquery > range > index > ALL

  1. possible_keys

显示查询可能使⽤哪些索引来查找,使⽤索引优化 sql 的时候⽐较重要。

  1. key

这⼀列显示 mysql 实际采⽤哪个索引来优化对该表的访问,判断索引是否失效的时候常⽤。

  1. key_len

这一列显示了mysql在索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列。

  1. ref

ref 列展示的就是与索引列作等值匹配的值,常⻅的有:const(常量),func,NULL,字段名

  1. rows

估算 SQL 要查到结果集需要扫描读取的数据⾏数,这个值⾮常直观显示 SQL 的效率好坏,原则上 rows 越少越好。

  1. Extra

额外信息,里面也有⼀些重要的信息:

  • Using index:表示 MySQL 将使⽤覆盖索引,以避免回表。
  • Using where:表示会在存储引擎检索之后再进⾏过滤,其实也就是没有使用到索引,用的是全表扫描。
  • Using temporary :表示对查询结果排序时会使⽤⼀个临时表。