本文图与例子选自 xiaolincoding.com/mysql/index…
开门见山(个人总结
如果MySQL无法根据当前条件找出唯一的一条下潜路线或者索引有序性被破坏,此时索引失效(停止索引)
唯一的意思是仅有一条;找不到和找到好几个都不属于唯一
例子
常见的六种失效
MySQL索引以B+树为基础,在创建表时,InnoDB 存储引擎默认会创建一个主键索引,也就是聚簇索引,其它索引都属于二级索引。其中主键索引存放了数据,二级索引存放了主键,使用二级索引会产生回表操作
对索引使用左或者左右模糊匹配
对索引使用左模糊好理解
select * from t_user where name like '%林';
MySQL的字符串比较是从左往右以此比较的,使用左模糊就意味着,只要是个以林为后缀的字符串就符合要求小林,1林,2林等等;
而从B+树的角度看,这些字符串可能分布在树的各个位置,被查找数据是无序的,B+树完全无法找到唯一的下潜路径,不如直接全表扫描
对索引使用右模糊好
select * from t_user where name like '林%';
由上面可知,索引可以找到唯一的一条下潜路径,直到最终定位到一个子树上,这个子树的name都是以林开头的;这时索引结束,直接移动到子节点上,转为range。
对索引使用函数
select * from t_user where length(name)=6;
我们的索引是以name的值为基础建立的,在name层面是有序的,但在length(name)无法保证有序性,当前节点的左侧和右侧都有可能存在长度为6的字符串,MySQL无法根据当前条件找出唯一的一条下潜路线
比如你站在h点,你会发现往左往右都对
被函数处理的数值,无法保证其有序性和原始数值相同
对索引进行表达式计算
select * from t_user where id + 1 = 10;
实际上这个例子不太好,因为只是简单的 +1 并不影响原始的有序性,路径也是唯一的,实际上从理论上是可以用索引的;但在实际中表达式运算可能很复杂,以至于其y值可能解出多个x值;这时候x是不唯一的,MySQL无法找到唯一的下潜路径
更合适的例子
select * from t_user where id*id = 4;此时
id = 2 or -2;此时你站在0点,你会发现往左往右都对
对索引隐式类型转换
这一条涉及到MySQL的特性
MySQL 在遇到字符串和数字比较的时候,会自动把字符串转为数字,然后再进行比较。
- 当索引值为字符串,条件是数字时;MySQL会去转换索引值,此时类似于对索引使用函数;有序性被破坏,MySQL无法找出唯一的一条下潜路径
- 当索引值为数组,条件是字符串时,被转换的是条件,可以继续走索引
联合索引非最左匹配
在联合索引的情况下,数据是按照索引第一列排序,第一列数据相同时才会按照第二列排序。 也就是说,如果我们想使用联合索引中尽可能多的列,查询条件中的各个列必须是联合索引中从最左边开始连续的列。如果我们仅仅按照第二列搜索,肯定无法走索引。
这个好理解,如果我们的索引是(a, b, c),但查询条件是b or c or b and c;此时等同于不存在索引,MySQL当然也无法根据这些条件去找到唯一的下潜路径
这里还有个索引下推的知识点,当查询条件为
a and c时可以触发
WHERE 对非索引列执行 or 运算
显而易见,对非索引列执行查找只能全表扫描;MySQL找不到索引路径;
当然,如果两个都是索引,MySQL可以分别索引,然后求并集;
总结
今天给大家介绍了 6 种会发生索引失效的情况:
- 当我们使用左或者左右模糊匹配的时候,也就是
like %xx或者like %xx%这两种方式都会造成索引失效;- 当我们在查询条件中对索引列使用函数,就会导致索引失效。
- 当我们在查询条件中对索引列进行表达式计算,也是无法走索引的。
- MySQL 在遇到字符串和数字比较的时候,会自动把字符串转为数字,然后再进行比较。如果字符串是索引列,而条件语句中的输入参数是数字的话,那么索引列会发生隐式类型转换,由于隐式类型转换是通过 CAST 函数实现的,等同于对索引列使用了函数,所以就会导致索引失效。
- 联合索引要能正确使用需要遵循最左匹配原则,也就是按照最左优先的方式进行索引的匹配,否则就会导致索引失效。
- 在 WHERE 子句中,如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列,那么索引会失效。
结尾见山(个人总结
如果MySQL无法根据当前条件找出唯一的一条下潜路线或者索引有序性被破坏,此时索引失效(停止索引)
感谢小林coding提供的素材