MySQL索引失效的一些场景
前言
我使用的MySQL版本是8
具体开发场景建议对语句是否能走索引进行测试,本文章列举的场景仅供参考
PS:在查询语句前加explain可以查看该条语句执行的一些信息
失效场景
1.索引列使用了函数
在索引列使用了函数进行处理,比如👇
1 | SELECT id,name FROM table WHERE UPPER(name) = 'ABCD' |
这样的查询会导致索引列失效,因为数据库要先进行全表扫描,获得数据之后再进行截取、计算,导致索引索引失效。同时,这样会导致需要全表扫描所有值,然后再计算比较,会增加数据库的计算开销,引发性能问题。
2.索引列参与了计算
这种场景和第一种场景差不多,就是索引类参与了一些运算,比如👇
1 | SELECT id,name FROM table WHERE (id + 1) = 5 |
这样也会导致索引失效,和第一种原因一样,也会产生性能问题。
3.联合索引没有索引最左侧字段
如果使用了联合索引,多个字段作为索引,但在查询语句里面,没有使用最左侧的索引列,就会导致索引失效。
联合索引是遵循最左匹配原则,就是左侧的字段优先匹配,所以在建立联合索引的时候,也要把使用最频繁的列放在索引的左侧
比如我们根据字段(t1,t2,t3)建立了复合索引,则排序规则是先按t1字段进行排序,t1字段相同再按t2字段排序,当t1、t2字段都相同时再按t3字段进行排序。如果我们的查询条件中没有使用到第一列,那么该索引也就没有办法使用。
例如有 ‘id’ 和 ‘name’ 这两个列建立的联合索引,下面的查询语句就会导致索引失效👇
1 | SELECT id,name FROM table WHERE name = "张三" |
4.使用OR关键字
OR字段使用不当会导致索引失效
1 | SELECT id,name FROM table WHERE id = 5 OR name = "张三" |
上述语句,虽然id字段作为主键是有索引的,但or后的第二个条件没有索引,执行的时候需要全盘扫描,所以索引就失效了,解决办法:or前后执行的语句的字段都需要有索引
还有一种,当or的两边同时使用 “>” 和 “<” 的时候,索引也会失效
1 | SELECT id,name FROM table WHERE id > 5 OR id < 8 |
5.两列之间作比较
现在有两列带有索引的字段 “id” 和 “task_id”,但如果执行如下语句👇
1 | SELECT id,name FROM table WHERE id > task_id |
那么索引就会失效
6.数据类型不一致,发生隐式转换
这个很好理解,比如该字段是整数字段,比如自增的id,但输入查询语句中是字符串,比如
1 | SELECT id,name FROM table WHERE id = "5" |
这样的话索引就会失效
7.使用like语句
当使用了like语句,并且like的 “%” 在字符串的首位,索引就会失效,比如
1 | # 索引不生效 |
8. is null 和 is not null
当B-tree索引 is null 不会失效,使用 is not null 时会失效,位图索引 is null,is not null 都会失效
联合索引 is not null 只要在建立的索引列(不分先后)都会失效
1 | SELECT id,name FROM table WHERE name is not null |
9. not in
查询条件使用not in时,如果是主键则走索引,如果是普通索引,则索引失效
1 | # 主键索引id,索引生效 |