下面是一次explain返回的一条SQL语句的执行计划的内容:
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+--------------------------+
| 1 | SIMPLE | t2 | NULL | index | NULL | idx_abc | 198 | NULL | 5 | 20.00 | Using where; Using index |
+----+-------------+-------+------------+-------+---------------+----------+---------+------+------+----------+--------------------------+
一个执行计划中,共有12个字段,每个字段都挺重要的,先来介绍下这12个字段
假如我们有如下一张表(MySQL Innodb 5.7):
CREATE TABLE `t2` (
`id` INT(11),
`a` varchar(64) NOT NULL,
`b` varchar(64) NOT NULL,
`c` varchar(64) NOT NULL,
`d` varchar(64) NOT NULL,
`f` varchar(64) DEFAULT NULL,
PRIMARY KEY(id),
UNIQUE KEY `f` (`f`),
KEY `idx_abc` (`a`,`b`,`c`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
挑其中比较重要的几个字段分别介绍下他们的不同值都有哪些区别:
首先说type,他有以下几个取值内容,并给出了具体的SQL(PS:以下SQL是我实际测试过的,但是具体的表内容不一样可能最终优化器优化后的效果可能也不一样。)
explain select * from t2 where f='Hollis';
explain select * from t1 join t2 on t1.id = t2.id where t1.f1 = 's';
explain select * from t2 where a = 'Hollis';
explain select * from t2 where a > 'a' and a < 'c';
explain select c from t2 where b = 's';
explain select * from t2 where d = "ni";
需要注意的是,这里的index表示的是做了索引树扫描,效率并不高。以上类型由快到慢:
system> const > eq_ref >*ref>range> index *>ALL
再来说说possiblekeys 和 key,possiblekeys 表示查询语句中可以使用的索引,而不一定实际使用了这些索引。这个字段列出了可能用于这个查询的所有索引,包括联合索引的组合。而 key 字段表示实际用于查询的索引。如果在查询中使用了索引,则该字段将显示使用的索引名称;
接着说一个很重要!的字段,但是经常被忽略的字段extra,这个字段描述了 MySQL 在执行查询时所做的一些附加操作。下面是 Extra 可能的取值及其含义:
explain select * from t2 where d = "ni";
非索引字段查询explain select d from t2 where b = "ni";
未索引覆盖,用联合索引的非前导列查询explain select b,c from t2 where a = "ni";
索引覆盖explain select d from t2 where a = "ni" and b like "s%";
使用到索引下推。explain select a from t2 where b = "ni";
索引覆盖,但是不符合最左前缀explain select b from t2 where a in ('a','d','sd');
索引覆盖,但是前导列是个范围explain select * from t1 join t2 on t1.id = t2.id where a = 's';
explain select count(*),b from t2 group by b;
explain select count(*),b from t2 group by b;
参考:https://www.yuque.com/hollis666/xkm7k3/caou56 、 https://www.yuque.com/hollis666/xkm7k3/gb04a1yv2x6et411 首先看key字段有没有值,有值表示用到了索引树,但是具体是怎么用的,还得看type和extra。
简单说以下几个情况:
情况一:
explain select b from t2 where a in ('a','d','sd');
+----+-------+---------------+----------+--------------------------+
| id | type | possible_keys | key | Extra |
+----+-------+---------------+----------+--------------------------+
| 1 | index | NULL | idx_abc | Using where; Using index |
+----+-------+---------------+----------+--------------------------+
type = index , key = idxabc ,extra = Using where; Using index ,表示本次查询用到了idxabc的联合索引,但是没有遵守最左前缀匹配,或者遵守了最左前缀,但是使用了a字段进行了范围查询。所以,最终其实还是扫描了索引树的。效率并不高
情况二:
explain select * from t2 where a = 'Hollis';
+----+-------+---------------+----------+--------------------------+
| id | type | possible_keys | key | Extra |
+----+-------+---------------+----------+--------------------------+
| 1 | ref | idx_abc | idx_abc | NULL |
+----+-------+---------------+----------+--------------------------+
表示用到了索引进行查询,并且用到的是idx_abc这个非唯一索引。
情况三:
explain select * from t2 where f = 'f';
+----+-------+---------------+----------+--------------------------+
| id | type | possible_keys | key | Extra |
+----+-------+---------------+----------+--------------------------+
| 1 | const | f | f | NULL |
+----+-------+---------------+----------+--------------------------+
表示用到了索引进行查询,并且用到的是f这个唯一索引。
情况四:
explain select b,c from t2 where a = 'Hollis';
+----+-------+---------------+----------+--------------------------+
| id | type | possible_keys | key | Extra |
+----+-------+---------------+----------+--------------------------+
| 1 | ref | idx_abc | idx_abc | Using index |
+----+-------+---------------+----------+--------------------------+
表示用到了索引进行查询,并且用到了idx_abc这个索引,而且查询用到了覆盖索引,不需要回表。
情况五:
explain select b,c from t2 where d = 'Hollis';
+----+-------+---------------+----------+--------------------------+
| id | type | possible_keys | key | Extra |
+----+-------+---------------+----------+--------------------------+
| 1 | ALL | NULL | NULL | Using where |
+----+-------+---------------+----------+--------------------------+
表示没有用到索引。