「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. 范围查询之后范围查询之后的索引字段,会失效!!!但本身用来范围查询的那个索引字段依然有效,如图中的status 。
  • 而图中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)都在索引列上时,才能真正使用索引 。

经验总结扩展阅读