MySQL 联合索引最左前缀失效的六个真实场景

举报
yd_286814013 发表于 2026/10/25 14:22:25 2026/10/25
【摘要】 建了联合索引 (a, b, c),查询却走了全表扫描。这不是索引没生效,而是写法和索引结构对不上。下面这六种情况在实际项目里最常见。一、跳过了最左列。where b = 1 and c = 2 用不上 (a, b, c),因为 B+ 树先按 a 排序,a 不定下来后面无法定位。想让 b、c 生效,得单独给 (b, c) 建索引。二、范围查询截断后续列。where a = 1 and b > ...

建了联合索引 (a, b, c),查询却走了全表扫描。这不是索引没生效,而是写法和索引结构对不上。下面这六种情况在实际项目里最常见。

一、跳过了最左列。where b = 1 and c = 2 用不上 (a, b, c),因为 B+ 树先按 a 排序,a 不定下来后面无法定位。想让 b、c 生效,得单独给 (b, c) 建索引。

二、范围查询截断后续列。where a = 1 and b > 10 and c = 3,b 用了范围之后 c 无法再走索引定位。这时候可以考虑把 c 提到 b 前面,或者用覆盖索引绕过。

三、对索引列做函数运算。where date(create_time) = '2026-01-01' 会让索引失效,改成 create_time >= '2026-01-01' and create_time < '2026-01-02',范围查询仍然走索引。

四、隐式类型转换。字段是 varchar,查询写 where phone = 13800138000(数字),MySQL 会把字段转成数字比较,索引直接失效。加上引号就好。这一条在代码里最容易漏。

五、like 以通配符开头。like '%abc' 无法使用索引,like 'abc%' 可以。真要做前后模糊匹配,得上全文索引或者搜索引擎。

六、or 连接非索引列。where a = 1 or d = 2,只要 d 没索引,整个条件就会退化成全表扫描。把 or 拆成两条 union,或者给 d 也建索引。

排查手段:explain 看 type 和 key 两列,type 出现 ALL 就是全表扫描,key 为 null 说明没用上索引。再看 possible_keys 里有但 key 是 null,基本就是上面某一种。explain analyze 在 8.0 上还能看到实际行数,比估算更准。

另一个容易忽略的点:索引列的选择性。如果 a 只有两个取值,放在最左边几乎没过滤效果,把区分度高的列往前放,或者建联合索引时考虑 cardinality。用 show index from 表名 看 Cardinality 字段能判断。

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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