xplain语法---type字段案例
今天上班的时候遇到的一个慢日志问题,我在这里进行一个复盘,记录下,也帮助我自己对于explain语法的结果有个更深的了解。
我们都知道,explain语法可以查看执行计划,据说在5.1版本的时候有个大坑,可以直接执行DML???这个我没有考证过,因为这个版本太久了,没有使用过,有兴趣的同学可以测试一把。我把今天遇到的问题复盘一下,没有使用线上的数据,使用的是测试数据,首先我们创建一个表,然后插入几条数据,如下:
代码语言:javascript复制CREATE TABLE `test3` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`age` int(11) NOT NULL,
`score` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_age_score` (`age`,`score`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8
我们可以看到,这个表有一个主键,是id字段,一个二级联合索引,分别是age和score字段,然后我们插入数据:
代码语言:javascript复制mysql> select * from test3;
---- ----- -------
| id | age | score |
---- ----- -------
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
| 4 | 4 | 4 |
| 5 | 5 | 5 |
| 6 | 6 | 6 |
---- ----- -------
6 rows in set (0.00 sec)
接着我们执行一条SQL:
explain select age from test3 where score=4;
大家可以猜一下这个语句的结果是什么?
代码语言:javascript复制mysql> explain select age from test3 where score=4;
---- ------------- ------- ------- --------------- --------------- --------- ------ ------ --------------------------
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
---- ------------- ------- ------- --------------- --------------- --------- ------ ------ --------------------------
| 1 | SIMPLE | test3 | index | NULL | idx_age_score | 8 | NULL | 6 | Using where; Using index |
---- ------------- ------- ------- --------------- --------------- --------- ------ ------ --------------------------
1 row in set (0.00 sec)
可以看到explain的type值是index,这里有必要说一下type字段常用的几个值:
system:系统表,少量数据,往往不需要进行磁盘IO,速度最快
const: 常量链接
eq_ref: 主键索引或者非空唯一索引的等值扫描
ref: 非主键非唯一索引等值扫描
range: 索引范围扫描,常见于使用>,<,is null,between ,in ,like等运算符的查询中
index: 索引全表扫描,把索引从头到尾扫一遍,常见于使用索引列就可以处理不需要读取数据文件的查询
all: 全表扫描
可以看到,这里的type是index,也就是扫描了整个索引树,它的原因是索引树上的数据已经足够select语句返回了,因为age和score的数据都保存在二级联合索引树上,所以没有必要再去回到聚集索引树上去查询其他的字段了,关于聚集索引和二级索引的区别,如果大家不了解,后面我会专门写一篇文章进行分析。
我们再看上面的explain语句,我们可以发现这个语句的possible_keys值是null,而key的值是idx_age_score,扫描行数rows是6,也就是进行了全索引树的扫描,将表中的所有记录都进行了扫描,这种扫描方法如果数据量比较大,肯定是慢查询无疑,所以就督促业务方进行改正了。
再来看这个possible_keys=null的情况,需要了解的是,这个是index独有的一种结果,也就是说
当使用index访问方法来查询某个表时,possible_keys列是空的,而key列展示的是实际使用到的索引。
今天跟业务方讨论之后,发现他们创建的联合索引利用率不高,表中的数据也不多,一万来条,而查询语句对score列的依赖比较严重。所以针对上面这个sql,如果想要进行优化,最好的方法是将联合索引去掉,而在score列上单独创建索引,这样在数据量增长以后才能显著提高查询速度。