Mysql必知必会之索引失效

在日常开发中,肯定或多或少都遇到过索引失效的问题,这里我总结一下几种常见的索引失效的场景。为了方便解释,这里我再把图拿过来

不符和最左前缀匹配原则

当不符和最左前缀匹配原则的时候会导致索引失效。比如like以%开头,索引失效或者是联合索引没走第一个索引列。比如name和age的联合索引,当执行select * from user where name > '王五' and age > 22;时,那么如果要走索引的话,此时就需要扫描整个索引,因为索引列是先以name字段排序,再以age字段排序的,对于age来说,在整个索引中来说是无序的,从图中也可以看出 18、23...9,无序,所以无法根据二分查找定位到age > 22是从哪个索引页开始的,所以走索引的话要扫描整个索引,一个一个判断,最后还要回表,这就很耗性能,不如直接扫描聚簇索引,也就是全表扫描来的痛快。

索引列进行了计算

当对索引进行表达式计算或者使用函数时也会导致索引失效。这个主要是因为索引中保存的是索引字段是原始值,从上面画的图可以看出来,当经过函数计算后的值,也就没办法走索引了。

隐式转换

当索引列发生了隐式转换可能会导致索引失效。举个例子,mysql规定,当字符串跟数字比较时,会把字符串先转成数字再比较,至于字符串怎么转成数字,mysql有自己的规则。比如说,当我执行了下面这条sql时就会发生隐式转换

select * from `user` where name = 9527;

name字段是个varchar类型,9527,没加引号,是数字,mysql根据规则会把name字段的值先转换成数字,再与9527比较,此时由于name字段发生了转换,所以索引失效了

ALL说明没走索引,失效了。但是假设现在对age创建一个索引,执行下面这条sql

select * from `user` where age = '22';

此时age索引就不会失效,主要是因为前面说的那句话:当字符串跟数字比较时,会把字符串先转成数字再比较。于是'22'会被隐式转成数字,之后再跟age比较,此时age字段并没有发生隐式转换,所以不会失效。所以说,隐式转换可能会导致索引失效。

mysql统计数据误差较大

mysql统计数据误差较大也可能会导致索引失效,因为前面也说了,mysql会根据统计数据来计算使用索引的成本,这样一旦统计数据误差较大,那么计算出来的成本误差就大,就可能出现实际走索引的成本小但是计算出来的是走索引的成本大,导致索引失效。当出现这种情况时,可以执行analyze table 表名这条sql,mysql就会重新统计这些数据,索引就可以重新生效了

原文来自于三友的java日记

扫描二维码关注公众号,回复: 15484380 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_28165595/article/details/131031057