前言

我使用的MySQL版本是8

具体开发场景建议对语句是否能走索引进行测试,本文章列举的场景仅供参考

PS:在查询语句前加explain可以查看该条语句执行的一些信息

1.png

2.png

失效场景

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
2
3
4
5
# 索引不生效
SELECT id,name FROM table WHERE name like "%三"

# 索引生效
SELECT id,name FROM table WHERE name like "张%"

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
2
3
4
5
# 主键索引id,索引生效
SELECT id,name FROM table WHERE id not in (5,6)

# 普通索引name,索引生效
SELECT id,name FROM table WHERE name not in ("张三","王五")