深入MySQL优化-索引失效

避免索引失效

  • 尽量选择全值匹配
  • 最佳左前缀法则:如果索引了多列,要遵守最左前缀法则。指的是查询从索引的最左前列开始且不跳过索引中的列。
  • 不要在索引列上做任何(计算,函数,类型转换),会导致索引失效而转向全表扫描
  • 尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select*
  • MySQL在使用不等于(!=或者<>)(因为!=实际上是个范围)时的时候无法使用索引会导致全表扫描,在使用范围时也不能使用。
  • is null ,is not null也无法使用索引

最佳左前缀法则

所谓的最佳左前缀法则就是查询时使用到的字段顺序需要满足建立索引时的字段顺序。
看下面的栗子:
在staffs表上,创建(name,age.pos)的索引

create index idx_nap on staffs(name,age,pos);

在这里插入图片描述
可以看到在index表上,name,age,pos的Seq_in_indexx是按照建立索引时的顺序从小到大的,即name>age>pos。记住这个顺序,现在继续往下看。
先进行全值匹配

explain select * from staffs 
where name='z3' and age =21 and pos='manager';//顺序是name->age->pos

Explain:
在这里插入图片描述
type为ref,key为我们先前创建的索引idx_nap,ref为三个const引用。上面的查询语句成功的利用了我们创建的索引。现在继续往下看

依然是全值匹配,但是不按照索引创建时字段的顺序进行查询

explain select * from staffs 
where age =21 and name='z3'  and pos='manager';//顺序是age->name->pos

Explain:
在这里插入图片描述
Explain信息和前面的按照索引字段顺序查询的全值匹配是一样的。我们先得出一个结论全值匹配无需理会左前缀法则,只要是全值匹配就能够成功使用索引我们继续往下看

不继续全值匹配了,从索引字段中抽出两个进行测试

explain select * from staffs 
where name='z3'  and pos='manager';//顺序是name->pos

Explain:
在这里插入图片描述
我们发现idx_nap仍然有被使用,但是key_len长度为74,同时ref只有一个const。我们发现只有第一个name字段使用了索引,而pos字段没有使用索引。我们得出另一个结论左前缀法则就像是爬楼梯,查询时字段的顺序一定要按照建立索引时字段的顺序(全值匹配除外),将name字段比作1楼,age字段比作2楼,pos字段比作3楼。楼梯只能一楼一楼上,如果上了一楼之后再上3楼,不经过2楼,就只能使用到1楼的索引

我们再继续看下

explain select * from staffs 
where age =21;//只使用了age字段

Explain:
在这里插入图片描述
根据我们前面的比喻,age为2楼。我们在上述查询中直接使用了age而避开了name,这就相当于绕过1楼爬2楼,所以此时也没有利用到索引。


尽量使用覆盖索引
explain select * from staffs //使用select*
where age =21 and name='z3'  and pos='manager';

Explain:
在这里插入图片描述

explain select name,age,pos from staffs //覆合索引
where age =21 and name='z3'  and pos='manager';

在这里插入图片描述
两个Explain相比较,我们发现使用覆合索引时,后者的Extra多了Using index

覆合索引有什么好处

MySQL可以利用索引返回SELECT列表中的字段,而不必根据索引再次读取数据文件。如果SELECT列表中的字段都包含在索引内,成为覆盖索引,这样就不再需要回表操作。索引条目远小于数据行的大小,如果只需要读取索引,那么MySQL就会极大地减少数据访问量。

猜你喜欢

转载自blog.csdn.net/weixin_40288381/article/details/87948501