一.概念
索引失效是指在查询时,数据库引擎无法使用索引来加速查询,从而导致查询性能下降。常见的索引失效原因有以下几种:
- 索引列没有被包含在查询条件中。如果查询条件中没有包含索引列,那么数据库引擎无法使用索引来加速查询。
- 索引列被函数或表达式包含。如果查询条件中的索引列被函数或表达式包含,那么数据库引擎无法使用索引来加速查询。
- 索引列被类型转换。如果查询条件中的索引列被类型转换,那么数据库引擎无法使用索引来加速查询。
- 索引列上存在函数或操作符。如果查询条件中的索引列上存在函数或操作符,那么数据库引擎无法使用索引来加速查询。
- 索引列上存在模糊查询。如果查询条件中的索引列上存在模糊查询,如使用LIKE操作符,那么数据库引擎无法使用索引来加速查询。
- 索引列上存在NULL值。如果查询条件中的索引列上存在NULL值,那么数据库引擎无法使用索引来加速查询。
- 索引列被过滤器过滤。如果查询条件中的索引列被过滤器过滤,那么数据库引擎无法使用索引来加速查询。
为避免索引失效,需要在设计索引时尽可能考虑到查询条件,并使用合适的索引类型。同时,需要注意避免在查询条件中使用函数、操作符、模糊查询等会导致索引失效的操作。
二.索引失效的10种场景
- 不满足最左匹配原则
在建立联合索引顺序为:code,age,name
通过最左匹配原则需要通过code来走索引,否则失效 - 使用了select*
在《阿里巴巴开发手册》中明确说过,查询sql中禁止使用select * 。
使用select *,从执行结果看,走了全表扫描,没有用到任何索引,查询效率是非常低的。
如果查询的时候,只查我们真正需要的列,而不查所有列,结果会怎么样?
全索引扫描要比全表扫描效率更高。
其实这里用到了:覆盖索引。
如果select语句中的查询列,都是索引列,那么这些列被称为覆盖索引。这种情况下,查询的相关字段都能走索引,索引查询效率相对来说更高一些。
而使用select *查询所有列的数据,大概率会查询非索引列的数据,非索引列不会走索引,查询效率非常低。 - 索引列上有计算
如果SQL语句用到主键索引,并在主键上操作,那么就会失效 - 索引列用了函数
使用函数也会失效 - 字段类型不同
如果code字段的类型是varchar,而传参的类型是int,两种类型不同导致失效。
mysql发现如果是int类型字段作为查询条件时,它会自动将该字段的传参进行隐式转换,把字符串转换成int类型。
为什么字符串类型的字段,传入了int类型的参数时索引会失效呢?
答:根据mysql官网上解释,字符串’1’、’ 1 '、'1a’都能转换成int类型的1,也就是说可能会出现多个字符串,对应一个int类型参数的情况。 - like左边包含%
但如果like用的不好,就可能会出现性能问题,因为有时候它的索引会失效。
目前like查询主要有三种情况:
- like ‘%a’
- like ‘a%’
- like ‘%a%’
其中下面两种无法走索引,会变成全表扫描
- 列对比
如果把两个单独建了索引的列,用来做列对比时索引会失效。 - 使用or关键字
如果使用了or关键字,那么它前面和后面的字段都要加索引,不然所有的索引都会失效,这是一个大坑。 - Not in和not exists
in和exists关键字可以走索引
主键字段中使用not in关键字查询数据范围,任然可以走索引。而普通索引字段使用了not in关键字查询数据范围,索引会失效。
而sql使用not exists也会失效 - Order By的坑
哪些情况可以走索引
满足最左原则
Order by配合where一起遵循最左匹配原则
联合索引字段下,排序相同的情况下
联合索引字段下,where和order by一起使用
哪些情况不可以走索引
Order by没有加where或limit不走索引
对不同的索引做order by
不满足最左匹配原则
排序不同