上篇文章我们剖析了慢sql如何排查,每每Mysql的索引失落效是一个比较常见的问题,这种情形一样平常会在慢sql发生时须要考虑,考虑是否存在索引失落效的问题。
在排查索引失落效的时候,第一步一定是找到要剖析的SQL语句,然后通过explain查看他的实行操持。紧张关注type、key和extra这几个字段。
一个实行操持中,共有12个字段,每个字段都挺主要的,先来先容下这12个字段

通过key+type+extra来判断一条SQL语句是否用到了索引。如果有用到索引,那么是走了覆盖索引呢?还是索引下推呢?还是扫描了整颗索引树呢?或者是用到了索引跳跃扫描等等。
一样平常来说,比较空想的走索引的话,该当因此下几种情形:
首先,key一定要有值,不能是NULL其次,type该当是ref、eqref、range、const等这几个还有,extra的话,如果是NULL,或者usingindex,usingindex condition都是可以的如果通过实行操持之后,创造一条SQL没有走索引,比如type=ALL,key=NULL,extra= Using where。
那么就要进一步剖析没有走索引的缘故原由了。我们须要知道的是,到底要不要走索引,走哪个索引,是MySQL的优G化器决定的,他会根据预估的成本来做一个决定。
那么,有以下这么几种情形可能会导致没走索引:
没有精确创建索引:当查询语句中的where条件中的字段,没有创建索引,或者不符合最左前缀匹配的话,便是没有精确的创建索引。引区分度不高:如果索引的区分度不足高,那么可能会不走索引,由于这种情形下走索引的效率并不高。表太小:当表中的数据很小,优化器认为扫全表的本钱也不高的时候,也可能不走索引查询语句中,索引字段由于用到了函数、类型不一致等导致了索引失落效上述对应情形逐一剖析
如果没有精确创建索引,那么就根据SQL语句,创建得当的索引。如果没有遵守最左前缀那么就调度一下索引或者修正SQL语句。索引区分度不高的话,那么就考虑换一个索引字段。表太小这种情形确实也没啥优化的必要了,用不用索引可能影响不大的排查详细的失落效缘故原由,然后针对性的调度SQL语句就行了。可能导致索引失落效的情形创建一张表(msql5.7)
CREATE TABLEmytable(id int(11) NOT NULL AUTO INCREMENT,name varchar(50) NOT NULL,age int(11) DEFAULT NULL,create time datetime DEFAULT NULL, PRIMARY KEY (id)UNIOUE KEY name(name),KEY age( age),KEY create time (create time))ENGINE=INnODB DEFAULT CHARSET=utf8mb4;insert into mytable(id,name,age,create time)values(1,"cw",20,now());insert into mytable(id,name,age,create time)values(2,"cw1",21,now());insert into mytable(id,name,age,create time)values(3,"cw2",22,now());insert into mytable(id,name,age,create time)values(4,"cw3",20,now());insert into mytable(id,name,age,create time)values(5,"cw3",15,now());insert into mytable(id,name,age,create time) values(6,"cw4",43,now());insert into mytable(id,name,age,create time)values(7,"cw5",32,now());insert into mytable(id,name,age,create time)values(8,"cw6",12,now());insert into mytable(id,name,age,create time) values(9,"cw7",1,now());insert into mytable(id,name,age,create time)values(10,"cw8",43,now());
参与索引打算
以上SQL是可以走索引的,但是如果我们在字段中增加打算的话,就会索引失落效:
如何以下形式打算可以走索引
对索引列进行函数操作
以上走索引的,增加函数操作的话,就会索引失落效
利用or
select from mytable where name = 'cw' and age>18;
但是如果利用or的话,并且or两边存在<或者>的利用,就会索引失落效
select from mytable where name = 'cw' or age>18;
如果OR两边都是=判断,并且两个字段都有索引,那么也是可以走索引的,如:
select from mytable where name = 'cw' or age=18;
like操作
select from mytable where name like '%cw%';
select from mytable where name like '%cw';
select from mytable where name like 'cw%';
select from mytable where name like 'c%w';
隐式类型转换
select from mytable where name = 1;
以上情形,name是一个varchar类型,但是我们用int类型查询,这种是会导致索引失落效的。
这种情形有一个特例,如果字段类型为int类型,而查询条件添加了单引号或双引号,则Mysql会参数转化为int类型,这种情形也能走索引:
select from mytable where age= '1';
不即是比较
以下可能走索引的
is not null
以下情形索引失落效
order by
当进行order by的时候,如果数据量很小,数据库可能会直接在内存中进行排序,而不该用索引。
in利用in的时候,有可能走索引,也有可能不走,一样平常在in中的值比较少的时候可能会走索引优化,但是如果选项比较多的时候,可能会不走索引:
select from mytable where name in ('cw');
select from mytable where name in ('cw','hshs','cww');
总结
本篇剖析了索引失落效的不同情形,旨在帮忙大家在事情中快速定位自己写的sql没走索引的情形剖析,更快速的办理索引失落效的问题。