MySQL中索引失效是怎么回事?

202 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天

一、索引失效的5种情况

image.png image.png

  • 被索引字段,发生了隐式类型转换;mysql在SQL语句执行过程中,会自动将sql执行中,与原字段类型不匹配的值进行转换

  • 被索引字段使用了表达式计算,比如select * from user where age-2=5

  • 被索引字段使用了函数,比如select * from user where left(phone,3) = '133'

  • 被索引字段使用了函数,比如select * from user where left(phone,3) = '133' ; select * from user where pone like = '133%' 是走索引的。

  • 在like关键字后,使用了左模糊匹配"%向前"、"%向前" 比如select * from user where address like "%杭州下沙%";;;;;like "向前%" 可以使用索引

  • 被使用的索引字段,不是联合索引的最左字段

  • 最后注意:以上5种情况,如果查询过程中发生了索引覆盖,也就是不需要回表时,索引树还是会被使用的。
    select id,address from user where address like "%杭州下沙%"; 会走索引。

二、原理:

1.索引字段依赖B-tree索引树的遍历的;索引树的遍历依赖索引树底层叶子节点的有序性;当被索引字段进行了隐式类型转换、表达式计算、函数计算,有可能这个字段新的排序和原来在索引树叶子节点层排列顺序不一样了,这就会破坏了索引叶子节点层的有序性;当sql语句执行时,mysql数据库SQL语句执行器无法判断原来的索引树是否还能被检索使用,所以最好结果就是SQL语句执行器不适用该索引了;直观感受我们期望的索引失效了

2.mysql中的索引树检索遵循最左匹配。B-tree索引叶子节点层的有序性;如果直接使用索引键的中部或者后部进行sql查询,由于违背了索引的最左匹配原则,mysql的sql语句执行器不能检索到索引。

思考题:发生索引覆盖时,idx_address索引虽然被使用了,但是使用索引树的时间复杂度还是O(log N)吗?