Explain索引优化实例

关于Explain的执行计划详细信息请参考上篇文章。下面用Explain分析案例。
首先建立表student结构,该表目前没有索引,如下:
这里写图片描述

一、案例1

案例:查询学号student_num=1,年龄age>20,班级class=1的记录
这里写图片描述

id为1,只有一次查询;
select_type为SIMPLE,表示该条SQL为简单查询;
table为student,表示查询来自student表;
type为ALL,表示遍历全表,查询到记录;
possible_keys为NULL,表示理论上没有应用到student表中的索引;
key为NULL,表示实际上也没有应用到student表上的索引;
key_len为NULL,表示用到的索引长度为0,因为没有用到索引;
ref为NULL,表示用到的索引的列为空,因为没有用到索引;
rows为6,表示为查询到需要的记录,读取了表中的6条记录;
Extra为Using where,表示使用了where条件进行过滤

优化1
下面在学号、年纪、班级上建索引:

create index index_num_age_class on student(student_num, age, class);

下面再执行案例中的SQL
这里写图片描述
从explain的执行计划信息可以看出,type=range,表示只检索给定范围的行,通过一个索引age来检索给定的范围;possible_keys表示理论上用到了index_num_age_class索引;key表示实际上也用到了index_num_age_class索引;key_len的长度为10,表示用到的索引长度为10,由于创建表时,student_num、age都是int类型的,并且默认可以为NULL的,在mysql中int类型占4个字节,NULL占一个字节,所以student_num和age分别占5个字节,最终在student_num、age和class三个字段上建立的复合索引,只用到了前两个索引,所以key_len的长度为10。
优化1与案例比,有了一定的优化,用到了部分索引,并且检索类型是range范围。

优化2
下面删除原来的索引,在student_num,class和age上建索引,注意顺序与优化1中的不同;

create index indext_num_class_age on student(studeng_num, class, age);

下面再执行案例中的查询语句
这里写图片描述
从explain的执行计划信息中可以看出,type=range,依然是范围检索;但是用到的索引长度key_len变成了15,表示用到的索引更多了,按照优化1中分析,student_num、class、age默认为空,分别占5个字节,共15个字节,因此建立的复合索引完全用上了,属于最好的情况;rows=1,表示只通过检索了一条记录就查到了索要的记录,如果百万级的数据,很显然这种检索的记录少,能够快速的找到需要的记录。
优化1中用到了部分索引,通过检索2条语句找到了索要的记录;而优化2中用了全部的索引,只检索1条语句就找到了索要的记录。

案例2

本案例执行两个表的联合查询。继续用案例1中student表,然后创建teacher表,表如下:
这里写图片描述
目前student和teacher表均无索引,查询班级class相等的学生和老师,用explain分析如下:
这里写图片描述
通过执行计划分析,可以看出,查student和teacher表时,type类型均为ALL,表示全表查询,也没有索引,对于百万级数据没什么效率可言。

优化1
在student的class字段上建立索引

create index id_class on student(class);

然后重新用explain分析执行计划信息:
这里写图片描述
发现与案例2比一样,没有什么改变,没什么优化。

优化2
下面删除student的字段class上的索引,在teacher的class字段上建立索引

 create index id_class on teacher(class);

下面重新执行explain的执行计划分析
这里写图片描述
发现在查询teacher表时,type类型为ref,使用到了索引扫描,用到的索引为id_class;由于在建class表时,class字段类型为int,默认为空的,所以key_len的长度为5。

优化1与优化2相比,优化2中检索了7行数据,优化1中检索了8行数据,因此优化2中检索了更少的数据获取需要的结果。
结论:对于左连接,索引一定要建立在右边的表(此地为teacher)上才会起作用;同样对于右连接,索引一定要建立在左边的表上才可以起作用。

同理,对于三表查询的,例如
select * from student left join teacher on student.class=teacher.class lefit join school on student.class=school.class;
在teacher和school的class上建立索引会发挥索引功效。

猜你喜欢

转载自blog.csdn.net/u010502101/article/details/81090237