联合索引最左匹配原则源于b+树按字段顺序排序的结构特性——必须从最左列开始才能利用有序性高效查找;跳过左列或范围查询后右侧字段失效,因后续字段仅在左侧值固定时局部有序。

MySQL 联合索引的最左匹配原则,本质是 B+ 树索引结构决定的查询行为规则——它不是 MySQL 的“约定”,而是数据有序存储和高效查找的必然要求。
为什么必须从最左边开始?
联合索引 (a, b, c) 在磁盘上构建的是一棵 B+ 树,排序逻辑严格按字段顺序:先按 a 升序排列;a 相同时,再按 b 升序;a 和 b 都相同时,再按 c 升序。这意味着:
- a 列整体有序,可直接二分查找定位范围
- b 只在 a 值固定的前提下才局部有序
- c 只在 a 和 b 都固定的前提下才局部有序
- 跳过 a 直接查 b 或 c,相当于在一堆无序数据里找值,无法利用树结构加速
哪些查询能用上索引?
假设索引为 (gid, cid, sid),以下写法均可命中索引(MySQL 查询优化器会自动调整 WHERE 子句顺序):
-
WHERE gid = 1→ 使用 (gid) 索引片段 -
WHERE gid = 1 AND cid = 5→ 使用 (gid, cid) 片段 -
WHERE gid = 1 AND cid = 5 AND sid = 101→ 完整使用 (gid, cid, sid) -
WHERE cid = 5 AND gid = 1→ 仍有效,优化器重排为 gid 优先
但这些写法无法使用该联合索引:
-
WHERE cid = 5(跳过最左列 gid) -
WHERE gid = 1 AND sid = 101(跳过中间列 cid,sid 失效) -
WHERE sid = 101(只查最右列)
范围查询为什么会让右边字段失效?
因为范围操作(>、、<code>BETWEEN、LIKE 'abc%')破坏了后续字段的有序性:
-
WHERE gid = 1 AND cid > 3→ gid 可用,cid 可用(等值+范围),但 sid 不可用(范围之后中断) -
WHERE gid > 1 AND cid = 5→ gid 可用,cid 不可用(gid 是范围,其下所有 cid 值杂乱无序)
根本原因:B+ 树中,一旦某层节点是“范围扫描”,其子树不再保证下一列的全局有序,因此无法继续做索引驱动的精确查找。
实际设计联合索引要注意什么?
顺序不是随意定的,需结合查询模式和字段区分度综合判断:
- 把高频过滤条件放最左(如常用于 WHERE 的字段)
- 把高区分度字段前置(如用户 ID 比性别更适合作左列)
- 避免在联合索引字段中允许 NULL(含 NULL 的列不参与索引构建)
- 等值查询多、范围查询少时,把范围列尽量靠右;若必须用范围且要兼顾右边字段,考虑拆分或补充覆盖索引
记住:联合索引不是多个单列索引的叠加,而是一棵按字段顺序组织的单一 B+ 树。理解它怎么“排”、怎么“找”,比死记规则更有用。










