MySQL 索引的最左前缀匹配原则是什么?
- 标签:后端、MySQL、数据库
🏛 业务架构师
最左前缀匹配是联合索引的使用规则:索引 (a, b, c) 相当于先按 a 排序、a 相同再按 b、再按 c。所以查询条件必须从最左列开始连续命中——where a=? and b=? 能用,where b=? 用不上(b 在全局是无序的)。
业务上我把它理解为:联合索引是把业务查询模式固化成物理结构。以电商订单为例,后台和用户侧最高频的查询是"某用户的某些状态的订单按时间倒序",那么 (user_id, status, created_at) 就是正确设计;where status=? 这种运营全局查询则走别的索引或走从库/ES。
落地经验有三条:
- 等值条件列在前,范围条件列在后:范围列之后的列无法继续走索引,
(user_id, created_at)的设计里时间放最后; - 先分析真实查询分布再定索引顺序:我会拉慢查询日志和调用量统计,让出现频率最高的等值查询吃到完整索引;
- 索引可以复用:已有 (a,b,c) 就不必再建 (a)、(a,b),索引是写性能的税,能省一条是一条。
一句话:最左前缀不是背规则,而是逼着团队在建模阶段就想清楚"这个表未来会被怎么查",这本身就是业务架构设计。
🏗 系统架构师
最左前缀是指联合索引 (a, b, c) 只能从最左列开始连续命中:查询条件有 a 可以用索引,a+b、a+b+c 最优;只有 b 或 c 则走不了这棵 B+ 树(除非索引跳跃扫描)。因为 B+ 树是先按 a 排序、a 相同再按 b 排序,跳过 a 就失去了有序性,这是数据结构决定的,不是优化器偷懒。
工程上的典型应用:
- 范围查询列放最后:
a=1 and b>5 and c=3,索引 (a, c, b) 让 a、c 都走等值匹配,只有 b 走范围; like 'xx%'能命中索引,like '%xx'不能;- 带范围条件时后续列停止匹配,
a between之后的 b 只做索引下推过滤。
我做表设计时会拿真实查询 SQL 反推索引列顺序:等值列在前、范围列在后、区分度高的在前,避免为了适配索引去改业务语义。
💻 全栈开发专家
联合索引 (a, b, c) 的匹配规则:查询条件必须从最左列 a 开始连续命中,才能用到该索引;跳过 a 或从中间列开始,索引基本失效。而且范围查询之后的列停止匹配。
sql
-- 索引 idx(a, b, c)
WHERE a = 1 AND b = 2 AND c = 3 -- 全命中
WHERE b = 2 AND c = 3 -- 不走(没带头)
WHERE a = 1 AND c = 3 -- 只用到 a
WHERE a > 1 AND b = 2 -- 只用到 a(a 是范围)MySQL 8 有 skip scan 优化,但只针对少数场景,别指望它。
落地实践:建联合索引时我会按"等值条件在前、范围条件在后、区分度高的在前"排;验证索引用了几列,看 EXPLAIN 的 key_len,比如 idx(a,b) 中 a 是 bigint(8B)+ b 是 int(4B),key_len = 12 说明两列都用上了,等于 8 就说明 b 没走索引——这是我评审 SQL 时最常用的手段。