explain语法---type字段案例

2019-11-06 11:53:27 浏览数 (1)

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列上单独创建索引,这样在数据量增长以后才能显著提高查询速度。

0 人点赞