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 常见的值 |
解释 |
例子 |
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; |
参考