mysql索引失效的场景:

1.like %%失效。

方案:改为like %,只写后面的%就能走索引。

2.虽然有索引,但是查询条件没有索引列或者order by 排序没有索引列。

方案:让查询条件有索引列

3.索引列存在null值的情况。

方案:索引列如果没有值,则给空字符串或者数字的0,总之就是不要设置null

4.非条件,如not exists, !=, not in。

如果查询条件为等值或范围查询时,索引可以根据查询条件去找对应的条目。反过来当查询条件为非时,索引定位就困难了,执行计划此时可能更倾向于全表扫描
方案:改为exists, =, in 这种正常的范围查询,而不是非范围查询

5.查询条件上包括函数。

如upper(),to_char(),to_date(),trunc等函数或者计算表达式 where name + last_name = ‘gg’ 这种都不行

6.当查询条件存在隐式转换时,索引会失效。

比如在数据库里id存的number类型,但是在查询时,却用了字符串 ‘’

7.组合索引,不是最左原则时。

例如组合索引是A,B,C三个字段,但是查询条件只有B,C时会导致索引失效

8.查询条件虽然有索引字段但是后面还有一个or 非索引字段,就会导致无法使用索引。

例如 where name= ‘张三’ or age > 10; name字段有索引,但是age没有索引的情况下,会导致name索引失效。

9.部分失效,范围查询右边的列失效。

例如联合索引有 (name,age, sex),然后select * from student where name ='a' and age>10 and sex = 1 这条sql虽然索引能够生效,但是只能命中name部分,age部分。但是sex部分不会用到。即只能使用联合索引中的一部分,索引断了一部分。

优化案例:

  1. 尽量用union all 替代 or 查询。
  2. 关于union和union all的使用,union会自动压缩多个结果集合中的重复结果,而union all则将所有的结果全部显示出来,不管是不是重复。 如果确定了查询结果是不重复的,即能够使用union all的则优先使用union all 而不是union。
  3. 当查询条件的值区分度越大,加索引的效果才越好。如果查询条件的区分度不大,不用加索引。比如一个表有100万数据,然后state字段的值有1,2,3。其中1有5万条,2有90万条,3有5万条。这时候如果是查询条件为where state = 1则索引有效果。如果是where state = 2 则mysql经过优化器判断后发现不走索引的效率比走索引的效率高,于是就不走索引了。
  4. 尽量用left join 和 inner join 替代exists, not exists语句。例如select * from shop_user a where not EXISTS (select * from shop_order b where a.id = b.uid) 语句可以用select * from shop_user a left join shop_order b on a.id = b.uid where b.uid is null 替换。查找b表中不在a表的数据
  5. 主键是整型自增,整型,等有序类型的效率比uuid字符串类型的效率高,这是由mysql的B+树存储结构决定的。
  6. left join 语句在右表的字段加索引效率高。例如 select * from student a left join score b on a.id = b.student_id 应该在score表的student_id加索引。
  7. 三表关联的时候应该在右表或中间表的字段加索引。例如:select * from student a left join score b on a.id = b.student.id left join subject c on a.id = c.student_id这时候应该在score表和subject表的student_id加索引。 select * from student a left join subject b on a.id = b.student_id left join score c on b.id = c.subject_id 这时候在subject表的student_id和score表的subject_id字段加索引。
  8. 如索引(a1,a2,a3,a4)select * from student a where a.a1='xx' and a.a2='x2' order by a.a4;这个sql虽然会命中索引a1,a2 但是因为order by a4,会导致出现Using filesort, 效率降低,就是因为索引要求是a1,a2,a3,a4的顺序。但是这个sql却要求按a4排序。建议改为select * from student a where a.a1='xx' and a.a2='x2' order by a.a3, a.a4即可。或select * from student a order by a.a1, a.a2, a.a3, a.a4