MySQL EXPLAIN
环境准备:MySQL5.7
创建测试表 :
CREATE TABLE `demo1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`key1` varchar(255) NOT NULL,
`key2` varchar(255) NOT NULL,
`key3` varchar(255) DEFAULT NULL,
`part_key_1` varchar(255) DEFAULT NULL,
`part_key_2` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `demo2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`key1` varchar(255) NOT NULL,
`key2` varchar(255) NOT NULL,
`key3` varchar(255) DEFAULT NULL,
`part_key_1` varchar(255) DEFAULT NULL,
`part_key_2` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
id
一般来说,每个Select关键字对应一个id,表示select查询的序列号。id越大越先执行;id相同从上往下执行。
- 单表查询
explain SELECT * FROM demo1 where id=1;
- 连接查询
explain SELECT * FROM demo1 INNER JOIN demo2 on demo1.id=demo2.id ;
连接查询,id是同一个,前面的是驱动表,后面的是被驱动表。
- 子查询
explain SELECT * FROM demo1 where key1 > (select id from demo2 ) ;
子查询的id是外层查询是不一样的。子查询更大,表示是最先执行的。
- union临时表
explain SELECT * FROM demo1 where key1>1 UNION SELECT * FROM demo1 where key2>3;
union临时表 id为NULL。
select_type
每个Select对应的查询类型
- SIMPLE :不包含 UNION 或者子查询的简单查询。
explain SELECT * FROM demo1 where id=1;
- PRIMARY : 包含了 UNION、UNION ALL 或者子查询的最外层查询。
explain SELECT * FROM demo1 where key1 > (select id from demo2 ) ;
- UNION :包含了 UNION 或者 UNION ALL 的非第一个查询。
explain SELECT * FROM demo1 where key1>1 UNION SELECT * FROM demo1 where key2>3;
- UNION RESULT : 一般用临时表来完成 UNION 查询的去重,对临时表的查询就UNION RESULT。
explain SELECT * FROM demo1 where key1>1 UNION SELECT * FROM demo1 where key2>3;
- DEPENDENT UNION:包含了 UNION 或者 UNION ALL 的非第一个查询,并且依赖于外层的查询。
explain select * from demo1 t1 where t1.key1 in (SELECT key1 FROM demo1 t1 where t1.key1>1 UNION SELECT key1 FROM demo2 t2 where t2.key2>3 and t2.key1=t1.key1);
- SUBQUERY:包含在 select 中的子查询(不在 from 子句中)的不相关子查询的第一个select。
explain SELECT * FROM demo1 where key1 > (select id from demo2 ) ;
- DEPENDENT SUBQUERY:相关子查询的第一个select。
explain SELECT * FROM demo1 t1 where t1.key1 > (select t2.id from demo2 t2 where t2.key2>t1.key2) ;
- DERIVED:包含在FROM子句的子查询中的SELECT,MySQL会将结果放到Derived table(派生表)中,以物化派生表的方式进行的查询 。
explain SELECT * from (SELECT key1 ,count(1) from demo1) as t
- MATERIALIZED:子查询物化之后,于外层查询进行连接查询的方式。
explain SELECT * from demo1 where key1 in(SELECT key1 from demo2)
-
UNCACHEABLE SUBQUERY:子查询,结果无法缓存,必须针对外部查询的每一行重新评估,不常用。
-
UNCACHEABLE UNION:UNION属于UNCACHEABLE SUBQUERY的第二个或后面的查询,不常用。
table
访问表的表名
partitions
当前查询匹配记录的分区,非分区表该值为NULL。
type
表示对单个表的访问方法
-
system:表中只有一条数据,且存储引擎的统计数据是精确的,innodb没有此类型。
-
const:通过主键或者唯一索引进行常数匹配的。
explain SELECT * FROM demo1 where id=1;
- eq_ref:执行连接查询时,被驱动表是通过主键或者不允许为NULL的唯一二级索引等值查询的方式访问,这几个条件缺一不可,这是最好的连接类型。
explain SELECT * FROM demo1 INNER JOIN demo2 on demo1.id=demo2.id ;
- ref:非唯一二级索引进行常量等值匹配查询。
explain SELECT * FROM demo1 where key2="22" ;
- ref_or_null:非唯一二级索引进行常量等值匹配查询,并且只可以为NULL时。
explain SELECT * FROM demo1 where key2="22" or key2 is NULL ;
-
fulltext:使用全文索引
-
index_merge:表示使用了索引合并的优化方法
-
range:索引范围查询
explain SELECT * FROM demo1 where id>1;
- index:使用覆盖索引,只需扫描索引树。
explain SELECT part_key_1,part_key_2 FROM demo1 where part_key_1>1;
-
unique_subquery:针对包含IN 子查询,通过主键或者不允许为NULL的唯一二级索引等值查询。
-
index_subquery:和unique_subquery类似,使用的是非唯一索引。
-
all:全表扫描。
possible_keys
可能用到的索引,如果是覆盖索引,该值为NULL
key
实际用到的索引
key_len
实际使用索引的长度,可以用来确定联合索引中实际使用了哪些列
ref
表示与索引列进行等值匹配的对象(常数、字段或者函数)
rows
完成查询预估要扫描的记录数
filtered
按表条件过滤的表行的估计百分比
Extra
其他额外的信息
- Using where:需要在server层进行where条件过滤
explain SELECT * FROM demo1 where key2 = 'a' and field1='d' ;
- Using index condition:使用索引条件下推
explain SELECT * FROM demo1 where part_key_1="a" and part_key_2>'b';
- Using index:使用覆盖索引
explain SELECT part_key_1,part_key_2 FROM demo1 where part_key_1>1;
- Using filesort:在内存或者磁盘文件中进行排序
explain SELECT * FROM demo1 where id>1 order by field1;
- Using temporary:使用临时表
explain SELECT DISTINCT field1 FROM demo1 where id>1 order by field1 ;
- Using join buffer:使用连接缓冲区
explain SELECT * FROM demo1 t1 INNER JOIN demo2 t2 on t1.field1=t2.field1 ;
需要优化的点
以下几种情况,可能就需要考虑进行优化:
- select_type 为 DEPENDENT SUBQUERY
- type 为 all,key 为 null
- Extra 为 Using filesort 、Using temporary、Using join buffer