MySQL 联合索引最左匹配原则详解

4次阅读

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

MySQL 联合索引最左匹配原则详解

mysql 联合索引的最左匹配原则,本质是 B+ 树索引结构决定的查询行为规则——它不是 MySQL 的“约定”,而是数据有序存储和高效查找的必然要求。

为什么必须从最左边开始?

联合索引 (a, b, c) 在磁盘上构建的是一棵 B+ 树,排序逻辑严格按字段顺序:先按 a 升序排列;a 相同时,再按 b 升序;ab 都相同时,再按 c 升序。这意味着:

  • a 列整体有序,可直接二分查找定位范围
  • b 只在 a 值固定的前提下才局部有序
  • c 只在 ab 都固定的前提下才局部有序
  • 跳过 a 直接查 bc,相当于在一无序数据里找值,无法利用树结构加速

哪些查询能用上索引?

假设索引为 (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(跳过中间列 cidsid 失效)
  • WHERE sid = 101(只查最右列)

范围查询为什么会让右边字段失效?

因为范围操作(>、<code>BETWEENLIKE 'abc%')破坏了后续字段的有序性:

  • WHERE gid = 1 AND cid > 3gid 可用,cid 可用(等值+范围),但 sid 不可用(范围之后中断)
  • WHERE gid > 1 AND cid = 5gid 可用,cid 不可用(gid 是范围,其下所有 cid 值杂乱无序)

根本原因:B+ 树中,一旦某层节点是“范围扫描”,其子树不再保证下一列的全局有序,因此无法继续做索引驱动的精确查找。

实际设计联合索引要注意什么?

顺序不是随意定的,需结合查询模式和字段区分度综合判断:

  • 高频过滤条件放最左(如常用于 WHERE 的字段)
  • 高区分度字段前置(如用户 ID 比性别更适合作左列)
  • 避免在联合索引字段中允许 NULL(含 NULL 的列不参与索引构建)
  • 等值查询多、范围查询少时,把范围列尽量靠右;若必须用范围且要兼顾右边字段,考虑拆分或补充覆盖索引

记住:联合索引不是多个单列索引的叠加,而是一棵按字段顺序组织的单一 B+ 树。理解它怎么“排”、怎么“找”,比死记规则更有用。

text=ZqhQzanResources