「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景( 三 )

1. 不满足最左前缀所谓最左前缀 , 可以想象成一个爬楼梯的过程,假设我们有一个复合索引:name , status,address,那这个楼梯由低到高依次顺序是:name,status,address,最左前缀 , 要求我们不能出现跳跃楼梯的情况 , 否则会导致我们的索引失效:?

  1. 按楼梯从低到高,无出现跳跃的情况--此时符合最左前缀原则,索引不会失效

「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景

文章插图
  1. 出现跳跃的情况
  • 直接第一层name都不走,当然都失效

「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景

文章插图
  • 走了第一层,但是后续直接第三层,只有出现跳跃情况前的不会失效(此处就只有name成功)

「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景

文章插图
  • 同时,这个顺序并不是由我们where中的排列顺序决定,比如:
    • where name='小米科技' and status='1' and address='北京市'
    • where status='1' and name='小米科技' and address='北京市'
这两个尽管where中字段的顺序不一样,第二个看起来越级了,但实际上效果是一样的
其实是因为我们MySQL有一个Optimizer(查询优化器) , 查询优化器会将SQL进行优化,选择最优的查询计划来执行 。
2. 范围查询之后范围查询之后的索引字段,会失效?。。〉旧碛美捶段Р檠哪歉鏊饕侄我廊挥行В缤贾械膕tatus 。
  • 而图中address失效了,对比一下长度便可看出来 。

「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景

文章插图
3. 索引字段做运算对索引字段做运算,使用函数等都会导致索引失效 。
「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景

文章插图
4. 字符串不加' '索引字段为字符串类型,由于在查询时,没有对字符串加单引号,MySQL的查询优化器,会自动的进行类型转换 , 造成索引失效 。
5. 避免select *危害
  • 消耗更多的 CPU 和 IO 以网络带宽资源
  • 可减少表结构变更带来的影响
  • 无法使用覆盖索引
覆盖索引尽量使用覆盖索引(索引列完全包含查询列),减少select *?
当查询列中包含了非索引项 , 虽然我们还是能够利用到索引 , 但是为了获取非索引项字段 , 我们需要回表去查询数据,效率会比较低 。?
6. or分割开的条件用or分割开的条件,如果or前的条件中的列有索引 , 而后面的列中没有索引 , 那么涉及的索引都不会被用到 。?
示例,name字段是索引列,而createtime不是索引列,中间是or进行连接是不走索引的 :
  • 因为有一个不走索引,又是or条件,两个都要判断一下,相当于不管如何,都还是得去走全表查询,没有利用到索引 。
explain select * from tb_seller where name='黑马程序员' or createtime = '2088-01-01 12:00:00'\G;
「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景

文章插图
7. 以%开头的Like模糊查询可以联系字典树Trie的匹配吧 。
  • 比如要找‘abc’ , 如果是%bc , 一开始的根都找不到了,自然没办法利用到索引树
  • 而如果是ab%,还能利用到前两个 。
  • %开头的失效 , %结尾的还能利用索引(实际上这里就相当于字符串的最左前缀原则 , 可以这么理解)

「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景

文章插图
解决方法:使用覆盖索引当真的需要两边都使用%来模糊查询时,只有当 作为模糊查询的条件字段(例子中的name)以及 想要查询出来的数据字段(例子中的 name & status & address)都在索引列上时,才能真正使用索引 。
关于覆盖索引,可以参考这篇 -> 索引原理,设计原则

「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景

文章插图
8. MySQL认为全表更快
「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景

文章插图
此处是由于数据的特殊性,‘北京市’所占的比例很高,还不如全表扫描
「MySQL高级篇」explain分析SQL,索引失效&&常见优化场景

文章插图
8.1 is null 和 is not null
本质上跟上边是一样的

推荐阅读