← 每日面试题 学习看板

MySQL中A,B,C的联合索引,按照 AB,AC,BC查询,能走索引吗?

面试题/03数据库中间件/01MySQL/03索引设计与优化(核心面试点)/MySQL中A,B,C的联合索引,按照 AB,AC,BC查询,能走索引吗?.md

面试记录 2026-09-17

题目:MySQL 中 A,B,C 的联合索引,按照 AB, AC, BC 查询,能走索引吗?

难度:medium

标签:db/mysql/index, mysql/index, difficulty/medium

评分:⭐⭐⭐☆(3/5)

我的回答

首先联合索引 ABC,按顺序来的话,ABC 间的索引 AB 跟 AC 是可以走部分的联合索引的,但是 BC 基本上不会走到联合索引。当然也有情况可能会走,就是 A 的数据很少,并且 A 的数据很单一的情况下,比如 A 是一个状态,这时候它可能做一个索引下推,在数据内部会做优化的时候,会进行类似于 UNION 将每个数据 UNION 一遍的情况。但正常情况下,B 级的查询是不会走索引的。想要做 B 级查询,可以单独建 B 级前缀的索引。

点评

优点:

不足:

补充:

完整讲解

第一部分:知识重点剖析

核心考点定位:理解联合索引的排序规则(B+ 树复合键排序)与 MySQL 8.0 的 Skip Scan 优化边界。

知识点拆解:

  1. 联合索引的排序规则:(A,B,C) 复合键的 B+ 树按字典序排序——先按 A 排序,A 相同时再按 B 排序,B 相同时再按 C 排序。所以查询能否命中索引取决于"是否提供了前缀"。
  2. AB 查询:WHERE a=? AND b=? 完整命中 A、B 两段定位。若没有 C 条件,C 不能作为定位,只能作为过滤(回表后判断)。
  3. AC 查询:WHERE a=? AND c=? 只有 A 段能定位,C 段中间隔了 B,无法利用排序,C 走过滤,Extra=Using where。
  4. BC 查询:WHERE b=? AND c=? 默认走不到索引——因为 A 未知,B 的排序在不同 A 之间不连续。MySQL 8.0+ 例外:若 A 基数很低(如 gender=0/1),优化器可能做 Skip Scan,把查询拆成 A=0 AND B=? AND C=? 和 A=1 AND B=? AND C=? 两段在索引内部完成,Extra=Using index for skip scan。
  5. 索引下推 ICP(Index Condition Pushdown):这是 MySQL 5.6 引入的优化,把非索引列的 WHERE 条件前推到索引扫描阶段做过滤,减少回表次数。Extra=Using index condition。它跟 Skip Scan 是两回事——ICP 减少回表次数,Skip Scan 让原本走不到的索引能走到。
  6. EXPLAIN 识别技巧:看 key 是否是目标索引、rows 是否显著下降、Extra 是否出现 Using index(覆盖)、Using index condition(ICP)、Using index for skip scan(Skip Scan)。

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. WHERE a IN (1,2,3) AND b=? 会走联合索引吗?
  1. WHERE a>? AND b=? 会怎样?为什么范围查询后面的列用不上?
  1. FORCE INDEX 能强行让 BC 走 (A,B,C) 索引吗?会有什么问题?

第三部分:面试者参考回答(口语化)

面试官您好,这个问题关键要看联合索引的排序规则。(A,B,C) 复合索引在 B+ 树上按字典序排——先按 A 排,A 相同再按 B 排,B 相同再按 C 排。所以查询要能命中索引,就必须能提供前缀。

AB 查询 WHERE a=? AND b=?:A 定位到一片区间,这片区间内 B 是有序的,所以 B 也能定位,两段都能用;如果 WHERE 没有 C,C 只能作为过滤条件在回表后判断。

AC 查询 WHERE a=? AND c=?:A 定位到区间后,中间隔了一个 B 未知,C 在这个区间里不再有序,所以 C 用不上索引定位,只能走过滤。EXPLAIN 会看到 Extra=Using where,key_len 只覆盖 A 段。

BC 查询 WHERE b=? AND c=?:默认走不到 (A,B,C) 索引。因为 A 未知,B 的有序性被 A 的分隔打散。但这里有个例外,MySQL 8.0 有个 Skip Scan(跳跃扫描) 优化:如果 A 的基数很低,比如是性别、状态这种只有几个值的字段,优化器会把这个查询在索引内部拆成 A=0 AND B=? AND C=?、A=1 AND B=? AND C=? 等多段分别扫描再合并。EXPLAIN 的 Extra 会显示 Using index for skip scan。

这里容易混淆的一个概念是 ICP(索引下推)。ICP 是 MySQL 5.6 加的优化,把 WHERE 里非索引列的条件前推到索引扫描阶段做过滤,减少回表次数,Extra 显示 Using index condition。ICP 不会让走不到的索引变走得到,它只是减少回表。Skip Scan 才是让原本用不到前缀列的查询也能用上索引。

所以工程实践上,如果有明确的 BC 查询模式,还是单独建 (B,C) 索引更稳妥,不要指望 Skip Scan 兜底——它的触发条件比较苛刻,A 基数低是硬要求。另外也不要用 FORCE INDEX 硬推,因为可能退化成全索引扫描,比全表扫描还慢。

https://chat.deepseek.com/share/6snsbux2u1oe10v9gu