补充-索引失效的几种情况

举报
yd_252271337 发表于 2026/11/12 09:01:19 2026/11/12
【摘要】 # 索引失效:明明建了索引,查询还是全表扫有次线上一个列表接口很慢,同事说「这个字段有索引啊」。我让他 EXPLAIN 一下,结果 type 是 ALL,全表扫描。索引是建了,但查询写法让它用不上。这种情况太常见了,这篇把索引失效的几个典型场景列一列。## 先确认是不是真失效别猜,用 EXPLAIN:```sqlEXPLAIN SELECT * FROM orders WHERE DATE(...

# 索引失效:明明建了索引,查询还是全表扫

有次线上一个列表接口很慢,同事说「这个字段有索引啊」。我让他 EXPLAIN 一下,结果 type 是 ALL,全表扫描。索引是建了,但查询写法让它用不上。这种情况太常见了,这篇把索引失效的几个典型场景列一列。

## 先确认是不是真失效

别猜,用 EXPLAIN:

```sql
EXPLAIN SELECT * FROM orders WHERE DATE(created_at) = '2026-11-07';
```

重点看 `key` 是不是 NULL。是 NULL 就说明没用索引,看 `type` 是 ALL 就更明确了。

## 场景一:对索引列做函数运算

```sql
-- 失效:对列做了函数
WHERE DATE(created_at) = '2026-11-07'

-- 有效:改成范围
WHERE created_at >= '2026-11-07' AND created_at < '2026-11-08'
```

索引存的是原始值,列一旦被函数包起来,数据库没法直接用索引里的顺序去比。同理 `substr`、`upper` 这些都会失效。

## 场景二:隐式类型转换

```sql
-- user_id 是 bigint,这里传了字符串
WHERE user_id = '12345'
```

字段是数字、条件传字符串,数据库会把列转成字符串再比,索引就废了。反过来,字符串字段传数字(比如手机号存 varchar 但传 int)也会。

这个坑最隐蔽,因为 SQL 能跑,结果也对,就是慢。排查时一定要看字段类型和参数类型是否一致。

## 场景三:前导模糊匹配

```sql
-- 失效
WHERE name LIKE '%张'

-- 有效(前缀确定)
WHERE name LIKE '张%'
```

索引是按前缀有序的,前面是通配符,没法定位起点,只能全扫。

## 场景四:最左前缀没满足

联合索引 `(a, b, c)`:

```sql
-- 有效:用到了 a
WHERE a = 1

-- 有效:用到了 a, b
WHERE a = 1 AND b = 2

-- 失效:没有 a,用不上这个联合索引
WHERE b = 2 AND c = 3
```

联合索引必须从最左列开始用。查询条件里没有最左列,整个索引就用不上。

## 场景五:范围条件之后的列失效

还是 `(a, b, c)`:

```sql
-- b 是范围条件,c 就用不上了
WHERE a = 1 AND b > 2 AND c = 3
```

范围条件后面的列,索引的有序性被打断。如果 c 是高频等值条件,考虑调整索引顺序。

## 场景六:OR 连接不同列

```sql
-- 两边的列都有索引才可能用上,否则容易全扫
WHERE a = 1 OR b = 2
```

OR 连接的列如果没有各自可用的索引,优化器干脆全表扫。可以改成 UNION,或者给两边都建索引。

## 场景七:不等于和 NOT IN

```sql
WHERE status != 'deleted'
WHERE id NOT IN (1,2,3)
```

不等于意味着要排除,范围太大,优化器往往选择全扫。如果这种查询很频繁,考虑换个建模方式,比如加一个「是否删除」的标记位只查有效数据。

## 场景八:统计信息过期

表数据变化很大,但统计信息没更新,优化器选错执行计划。

```sql
ANALYZE TABLE orders;
```

定期做,或者让数据库自动收集。

## 怎么避免

- 索引列上不做函数、不混类型
- 模糊查询尽量用前缀
- 联合索引按查询模式排最左列
- 范围条件放最后
- 用 EXPLAIN 验证,别凭感觉
- 上线前对高频 SQL 跑一遍执行计划

## 小结

索引失效不是因为没建索引,而是查询方式让优化器用不上。函数、类型转换、前导模糊、最左前缀、OR、不等于,这几个是高频原因。

记住一句话:索引是给「按原始值有序比较」用的。你对列做了加工、换了类型、模糊了前缀,它就帮不上忙了。养成 EXPLAIN 的习惯,比事后救火省心。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。