八股文:MySQL索引为什么会失效?

221 阅读5分钟

本文图与例子选自 xiaolincoding.com/mysql/index…

开门见山(个人总结

如果MySQL无法根据当前条件找出唯一的一条下潜路线或者索引有序性被破坏,此时索引失效(停止索引)

唯一的意思是仅有一条;找不到和找到好几个都不属于唯一

例子

常见的六种失效

image.png

MySQL索引以B+树为基础,在创建表时,InnoDB 存储引擎默认会创建一个主键索引,也就是聚簇索引,其它索引都属于二级索引。其中主键索引存放了数据,二级索引存放了主键,使用二级索引会产生回表操作

image.png

对索引使用左或者左右模糊匹配

对索引使用左模糊好理解

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无法根据当前条件找出唯一的一条下潜路线

image.png

比如你站在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 在遇到字符串和数字比较的时候,会自动把字符串转为数字,然后再进行比较

  1. 当索引值为字符串,条件是数字时;MySQL会去转换索引值,此时类似于对索引使用函数;有序性被破坏,MySQL无法找出唯一的一条下潜路径
  2. 当索引值为数组,条件是字符串时,被转换的是条件,可以继续走索引

联合索引非最左匹配

在联合索引的情况下,数据是按照索引第一列排序,第一列数据相同时才会按照第二列排序。 也就是说,如果我们想使用联合索引中尽可能多的列,查询条件中的各个列必须是联合索引中从最左边开始连续的列。如果我们仅仅按照第二列搜索,肯定无法走索引。

这个好理解,如果我们的索引是(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提供的素材