导致索引失效的几种案例
索引的原理就不过多介绍了,可以看之前的文章:Innodb索引
在使用过程中,会有很多导致索引失效的操作,来看以下几种案例:
1、不满足联合索引最左匹配原则
联合索引要正确使用需满足最左匹配原则,即:符合第一列才会继续判断后面的字段。
比如创建联合索引(a,b,c),以下情况都可以走索引:
where a=1; where a=1 and b=2; where a=1 and b=2 and c=3;
但是下面这几种情况就会导致索引失效:
where b=2; where c=3; where b=2 and c=3;
还有一个比较特殊的情况:
where a=1 and c=3
这种情况属于索引截断,不同MySQL版本处理方式不同:
(1)MySQL 5.5的处理:前面 a 会走索引,在联合索引找到主键后,开始回表,到主键索引读取数据行,再比对 c 字段的值。
(2)从MySQL 5.6之后,引入索引下推功能,可以在索引遍历过程中,对索引中包含的字段进行判断,直接过滤掉不满足条件的记录,减少回表次数。
2、where字句中的OR
如果where 字句中的OR条件,有一个字段不是索引列,则索引失效。
例如:id 是索引列,age 是非索引列,则下面的例子会造成索引失效
select * from t_user where id = 1 or age = 10
3、使用左或者左右模糊匹配的时候
就是 like %** 或 like %**% 会造成索引失效。
例如:name 是索引列,则下面的例子会造成索引失效
select * from t_user where name like '%明'
4、对索引使用函数
例如:name 是索引列,则下面的例子会造成索引失效
select * from t_user where length(name) = 3
5、对索引进行表达式运算
例如:id 是索引列,则下面的例子会造成索引失效
select * from t_user where id + 1 = 10
但是下面这样就可以使用索引
select * from t_user where id = 10 - 1
6、对索引进行隐式类型转换
例如:phone 是索引列,类型为 varchar。则下面的例子会造成索引失效
select * from t_user where phone = 13600001111
但是下面的例子就会使用索引:例如 id 是索引列,类型为 int。
select * from t_user where id = '1'
为什么第一个例子会造成索引失效,但是第二个却不会呢?
这是因为MySQL在遇到字符串和数字比较的时候,会把字符串转换成数字。