数据库索引失效:写了索引,却没走索引的几种情况

举报
yd_271358468 发表于 2026/11/08 01:12:57 2026/11/08
【摘要】 给表加了索引,查询还是慢,执行计划里显示全表扫描。这种情况很常见:索引建了,不等于查询会用它。索引失效的原因大多出在写法上,改写法比加索引更管用。对索引列做运算或函数处理这是最常见的失效原因。查询条件里对索引列用了函数或表达式,比如对日期字段用 DATE_FORMAT、对字符串用 SUBSTR、或者做加减乘除,数据库就没法直接用索引定位,只能把每一行都算一遍再比较。正确的做法是把运算挪到另一...

给表加了索引,查询还是慢,执行计划里显示全表扫描。这种情况很常见:索引建了,不等于查询会用它。索引失效的原因大多出在写法上,改写法比加索引更管用。

对索引列做运算或函数处理

这是最常见的失效原因。查询条件里对索引列用了函数或表达式,比如对日期字段用 DATE_FORMAT、对字符串用 SUBSTR、或者做加减乘除,数据库就没法直接用索引定位,只能把每一行都算一遍再比较。

正确的做法是把运算挪到另一边。想查某一天的数据,不要对日期列做函数转换,而是用范围条件:大于等于当天的零点、小于第二天的零点。条件里索引列保持“干净”,只出现列名本身,数据库才能走索引。

隐式类型转换

索引列是字符串类型,查询时传了数字,或者反过来,数据库会偷偷做类型转换,转换之后索引就失效了。典型的例子是手机号字段是 VARCHAR,查询时写成 WHERE phone = 13800000000(没加引号),数据库把每一行的 phone 转成数字再比较,全表扫描就来了。

避免的办法很简单:查询条件里值的类型和列定义保持一致。字符串列就用字符串字面量,数字列就用数字。类型不一致时别指望数据库帮你兜底,它兜底的方式就是放弃索引。

用了 OR,但不是所有分支都有索引

WHERE 条件里用 OR 连接多个条件,只要其中一个分支没有可用的索引,整个查询就可能退化成全表扫描。数据库要保证结果完整,不能只走一部分索引再拼另一部分的全表扫描,干脆全表扫一遍更省事。

如果 OR 的每个分支都有索引,数据库可以用索引合并;如果做不到,就把 OR 拆成 UNION:每个分支单独走自己的索引,最后合并去重。拆开写比硬拼一个 OR 更容易让优化器选对路。

LIKE 以通配符开头

LIKE 'abc%' 可以走索引,因为前缀是确定的,数据库能定位到范围。但 LIKE '%abc' 以通配符开头,前缀不确定,索引帮不上忙,只能逐行匹配。百分号在前面,索引就失效;在后面,索引还能用。

如果业务上确实需要模糊匹配,可以考虑全文索引,或者把查询改成前缀匹配加应用层过滤。不要在数据量大的表上对高频查询用前置通配符,那是全表扫描的稳定来源。

范围条件后面的列用不上

复合索引讲究最左前缀。索引是 (a, b, c),查询条件是 a = 1 AND b > 5 AND c = 10,c 这个条件是用不上索引的:b 是范围条件,范围后面的列在索引里的顺序就乱了,数据库只能在 b 的范围里再逐行过滤 c。

调整的思路是把等值条件往前放、范围条件往后放。索引设计时就应该把选择性高、经常做等值查询的列放在前面,范围查询的列放在后面。顺序错了,复合索引有一半是白建的。

结尾:先看执行计划,再动索引

遇到慢查询,第一步不是加索引,而是看执行计划。执行计划会告诉你这条查询到底走了哪个索引、扫描了多少行、过滤条件发生在哪一步。很多时候问题不在索引缺失,而在写法让已有索引失效。

索引是工具,不是越多越好。每多一个索引,写入就要多维护一份结构,查询优化器要选择的时间也变长。先把写法改对,让已有的索引真正被用上,再考虑是不是缺索引。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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