mysql explain 各字段的含义是什么?

24 阅读5分钟

简介

本篇文章主要介绍 explain <sql> 输出的结果中各字段的含义。比如我们先用如下的sql插入一些数据:

create table t1(id int(10) auto_increment primary key, content varchar(100) null);
create table t2(id int(10) auto_increment primary key, content varchar(100) null);
create table t3(id int(10) auto_increment primary key, content varchar(100) null);
create table t4(id int(10) auto_increment primary key, content varchar(100) null);
insert into t1(content) values(concat('t1_', floor(1+rand()*100)));
insert into t2(content) values(concat('t1_', floor(1+rand()*100)));
insert into t3(content) values(concat('t1_', floor(1+rand()*100)));
insert into t4(content) values(concat('t1_', floor(1+rand()*100)));

explain select * from t1 where id in (select id from t2); image.png

字段

id

SELECT 标记,当query中出现多个 SELECT 子句时,id的顺序代表了 SELECT 子句的执行顺序。大致分为以下几种情况:

  1. id相同,执行顺序由上至下
    explain select * from t1, t2, t3 where t1.id=t2.id and t2.id=t3.id; image.png 这个例子里,id都等于1,代表这几个查询的优先级相同,具体执行的查表顺序是t2->t1->t3,这个顺序是由优化器决定的。

  2. id不同,从大往小执行
    explain select * from t1 where t1.id = (select id from t2 where id = (select id from t3)) image.png 这个例子里,先执行id=3位于最里层的子查询select id from t3,然后依次向外。

  3. id有相同也有不同,不相同的从大往小执行,相同的从上往下执行
    explain select * from t1 where t1.id = (select id from t2 where id = (select id from t3)) and t1.id in (select id from t4) image.png 我们在后面追加一个in的子查询,这里的查表顺序是,t3->t2->t1->t4。

select_type

SELECT 类型,有下面几种常见取值

  1. SIMPLE:最简单的查询,没有联合查询(union)或子查询(subquery)
  2. PRIMARY:查询中若包含任何复杂查询,PRIMARY代表最外层的查询
  3. UNION:联合查询(union)中处于内层的查询
  4. UNION RESULT:从UNION表获取结果的SELECT
  5. SUBQUERY:如果包含了子查询,该子查询被标记为SUBQUERY
  6. DERIVED:在from子句中包含的子查询被标记为DERIVED

table

说明查询是基于那张表的,并不一定是实际的表,比如:

  1. <union M,N>: 输出结果集是 id=M 和 id=N 两个查询结果集的并集;
    explain select t1.* from t1 union select t2.* from t2; image.png
  2. <derived N>: 输出编号 id=N 的结果集,derived 表示这是一个派生结果集,如 FROM 子句中的查询。
  3. <subquery N>: 输出编号 id=N 的结果集,subquery 表示这是一个物化子查询(masterialization subquery

partitions

查询时匹配的分区信息,NULL 说明表没有被分区。

type

查询的访问类型,是影响性能比较重要的指标,有下面几种取值,性能依次从高到低:

  1. system:访问的系统表仅存在一条记录,很特殊的一种情况,一般遇不到

  2. const:当使用主键或唯一索引查询,且查询值是一个常量,这种情况下速度非常快,比如:
    explain select * from t1 where id=1; image.png

  3. eq_ref:当使用主键或唯一索引做连表查询(每个索引值仅返回一条记录)比如: explain select * from t1,t2 where t1.id=t2.id; image.png

  4. ref:使用普通索引查询,对每个索引值可以返回多条记录,我们可以给t1.content加上索引,然后查询:
    explain select * from t1 where t1.content='t1_12'; image.png

  5. fulltext:连表查询使用FULLTEXT索引

  6. ref_or_null:与ref类似,只是还需要判断是否为null,比如:
    explain select * from t1 where t1.content='t1_12' or t1.content is NULL; image.png

  7. index_merge:索引合并,一般出现在使用or的查询中,比如:
    explain select * from t1 where id=3 or seq=1; image.png

  8. unique_subquery:在某些使用唯一索引的in子查询中,替代eq_ref,比如:
    value IN (SELECT primary_key FROM single_table WHERE some_expr)

  9. index_subquery:与unique_subquery类似,在in子查询中使用,只是用于非唯一索引,比如:
    value IN (SELECT key_column FROM single_table WHERE some_expr)

  10. range:使用索引做范围查询,比如:
    explain select * from t1 where t1.id > 3; image.png

  11. index:类似于全表扫描,用到了索引树但没有进行过滤,因为索引树通常体积更小,所以比起全表扫描要快:
    explain select id from t1; image.png

  12. ALL:全表扫描,性能最差:
    explain select * from t1; image.png

possible_keys

查询时可能用到的索引(实际不一定用到)

key

查询时实际用到的索引,有可能possible_keys是NULL,但key有值,这在用覆盖索引查询时会出现,既无法通过索引过滤掉数据,但通过遍历索引树可以拿到查询要求的列,比如:
explain select id from t1;
image.png

key_len

用到的索引字节数,在不损失精度的情况下,用到的长度越短越好。

ref

显示索引的哪一列被使用了,取值有:

  1. const:当使用常量或等值查询
  2. func:查询条件使用了函数或发生了内部隐式转换
  3. 字段名:和key索引进行比较的列

rows

mysql判断为了完成查询,需要搜索的行数,越少越好,这是一个估计值。

filtered

filtered同样是一个估计值,它是一个百分比数(最大100),代表了按照type指定的查询方式,最终返回的行数占搜索行数的百分比。filtered 越大说明根据索引检查的行基本都要返回,这个索引越有效。如果我们有1000条数据,type=ALL,filtered=0.001,则最终只会有1条记录返回,此时如果能加个索引直接搜出这条记录,filtered就能提升到100。

Extra

额外信息

  1. Using filesort: 使用了文件排序
  2. Using temporary: 使用了临时表,常见于 order by 和 group by
  3. Using index: 覆盖索引,不用回表
  4. Using where: 索引有被用于where过滤

总结

本文简单介绍了 EXPLAIN 输出的各字段的含义,EXPLAIN 常被用来分析查询的执行效率。为了优化查询,重点关注type 字段。