EXPLAIN生成的查询计划中显示优化器计划如何执行查询

MySQL的EXPALIN是优化查询语句必不可少的工具,用户通过它可以获得查询计划的相关信息,查看优化器的选择。

Explain的结果各字段解释

执行计划分析结果示例如下:

1
2
3
4
5
6
7
8
mysql> explain delete from t_strategy_detail where id in (select strategy from robots where stop_time<1629782290 AND stop_kind > 0 AND stop_kind < 100);
+----+--------------------+------------------+------------+-------+---------------------------------+-----------------+---------+------+--------+----------+------------------------------------+
| id | select_type        | table            | partitions | type  | possible_keys                   | key             | key_len | ref  | rows   | filtered | Extra                              |
+----+--------------------+------------------+------------+-------+---------------------------------+-----------------+---------+------+--------+----------+------------------------------------+
|  1 | DELETE             | t_strategy_detail | NULL       | ALL   | NULL                            | NULL            | NULL    | NULL | 454862 |   100.00 | Using where                        |
|  2 | DEPENDENT SUBQUERY | robots           | NULL       | range | index_stop_time,index_stop_kind | index_stop_time | 5       | NULL |   2180 |     5.00 | Using index condition; Using where |
+----+--------------------+------------------+------------+-------+---------------------------------+-----------------+---------+------+--------+----------+------------------------------------+
2 rows in set (0.00 sec)
explain的列 解释
id 执行语句编号
select_type 查询类型:显示本行是简单还是复杂查询
table 涉及到的表
partitions 匹配的分区:查询将匹配记录所在的分区。仅当使用 partition 关键字时才显示该列。对于非分区表,该值为 NULL。
type 本次查询的表连接类型
possible_keys 可能选择的索引
key 实际选择的索引
key_len 被选择的索引长度:一般用于判断联合索引有多少列被选择了
ref 与索引比较的列
rows 预计需要扫描的行数,对 InnoDB 来说,这个值是估值,并不一定准确
filtered 按条件筛选的行的百分比
Extra 附加信息

select_type各种值的解释

select_type的值 解释
SIMPLE 简单查询(不使用关联查询或子查询)
PRIMARY 如果包含关联查询或者子查询,则最外层的查询部分标记为primary
UNION 联合查询中第二个及后面的查询
DEPENDENT UNION 满足依赖外部的关联查询中第二个及以后的查询
UNION RESULT 联合查询的结果
SUBQUERY 子查询中的第一个查询
DEPENDENT SUBQUERY 子查询中的第一个查询,并且依赖外部查询
DERIVED 用到派生表的查询
MATERIALIZED 被物化的子查询
UNCACHEABLE SUBQUERY 一个子查询的结果不能被缓存,必须重新评估外层查询的每一行
UNCACHEABLE UNION 关联查询第二个或后面的语句属于不可缓存的子查询

type各种值的解释

type的值 解释
system 查询对象表只有一行数据,且只能用于 MyISAM 和 Memory 引擎的表,这是最好的情况
const 基于主键或唯一索引查询,最多返回一条结果
eq_ref 表连接时基于主键或非 NULL 的唯一索引完成扫描
ref 基于普通索引的等值查询,或者表间等值连接
fulltext 全文检索
ref_or_null 表连接类型是 ref,但进行扫描的索引列中可能包含 NULL 值
index_merge 利用多个索引
unique_subquery 子查询中使用唯一索引
index_subquery 子查询中使用普通索引
range 利用索引进行范围查询
index 全索引扫描
ALL 全表扫描

key_len各种字段类型对应的长度

explain 中的 key_len 列用于表示这次查询中,所选择的索引长度有多少字节,常用于判断联合索引有多少列被选择了。下表总结了常用字段类型的 key_len:

列类型 KEY_LEN 备注
int key_len = 4+1 int 为 4 bytes,允许为 NULL,加 1 byte
int not null key_len = 4 不允许为 NULL
bigint key_len=8+1 bigint 为 8 bytes,允许为 NULL 加 1 byte
bigint not null key_len=8 bigint 为 8 bytes
char(30) utf8 key_len=30*3+1 char(n)为:n * 3 ,允许为 NULL 加 1 byte
char(30) not null utf8 key_len=30*3 不允许为 NULL
varchar(30) not null utf8 key_len=30*3+2 utf8 每个字符为 3 bytes,变长数据类型,加 2 bytes
varchar(30) utf8 key_len=30*3+2+1 utf8 每个字符为 3 bytes,允许为 NULL,加 1 byte,变长数据类型,加 2 bytes
datetime key_len=8+1 (MySQL 5.6.4之前的版本);key_len=5+1(MySQL 5.6.4及之后的版本) 允许为 NULL,加 1 byte

Extra常见值的解释

Extra 常见的值 解释 例子
Using filesort 将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序 explain select * from t1 order by create_time;
Using temporary 需要创建一个临时表来存储结构,通常发生对没有索引的列进行 GROUP BY 时 explain select * from t1 group by create_time;
Using index 使用覆盖索引 explain select a from t1 where a=111;
Using where 使用 where 语句来处理结果 explain select * from t1 where create_time='2019-06-18 14:38:24’;
Impossible WHERE 对 where 子句判断的结果总是 false 而不能选择任何数据 explain select * from t1 where 1<0;
Using join buffer (hash join) 关联查询中,被驱动表的关联字段没索引 explain select * from t1 straight_join t2 on (t1.create_time=t2.create_time);
Using index condition 先条件过滤索引,再查数据 explain select * from t1 where a >900 and a like ‘%9’;
Select tables optimized away 使用某些聚合函数(比如 max、min)来访问存在索引的某个字段是 explain select max(a) from t1;

参考