[面试题] 什么是最左前缀匹配?为什么要遵守?
📖 版块 A:知识讲解版 (温故知新)
-
定义:最左前缀匹配(Leftmost Prefix Match)是数据库复合索引(联合索引)中的一个核心准则。指在查询时,只有按照索引定义的列顺序,从最左边的列开始连续匹配,索引才能生效或部分生效。
-
匹配规则:
- 如果建立了索引
(a, b, c),查询条件包含a,则可以使用索引;包含a, b,也可以使用;包含a, b, c,全覆盖使用。 - 如果跳过中间列,如
a, c,则只能用到a列的索引,c列无法利用索引定位。 - 如果没有最左列,如只查询
b或c,则完全无法使用该索引(通常会触发全表扫描)。
- 如果建立了索引
-
失效场景:
- 断位:查询条件中不包含联合索引的最左列。
- 范围查询后失效:在联合索引中,如果某列使用了范围查询(如
>, ` 🧠 破局思路:面试官不仅想听你背诵“a-b-c”的规则,他更看重你是否理解 B+ Tree 联合索引的底层物理结构。真正的区分度在于:能否从 B+ 树的排序逻辑出发解释原因,以及能否点出“范围查询导致后续列失效”的底层细节。
💬 高手逐字稿:
简单来说,最左前缀匹配是指在使用联合索引时,MySQL 优化器会从索引的最左侧列开始逐一匹配。如果查询条件中没有包含索引的最左列,或者中间断开了,那么索引就无法被充分利用。
为什么要遵守这个原则?这得从 B+ Tree 的底层逻辑说起。
联合索引在物理存储上只有一棵 B+ 树,它的非叶子节点存储的是多个列的值。这些值是严格按照定义索引时的顺序进行排序的。以索引 (a, b) 为例,在 B+ 树中,数据首先按照 a 列进行全局排序;只有在 a 列的值相等的情况下,b 列的值才是局部有序的。
因此,如果你跳过 a 直接去查 b,由于 b 在全局范围内是乱序的,索引就无法通过二分查找快速定位,只能退化成全表扫描。这就是为什么要遵守最左前缀的原因:索引的有序性是建立在左侧列的基础之上的。
这里有一个非常容易被忽略的细节,就是“范围查询”对最左前缀的影响。
在联合索引中,如果我们在某个列上使用了范围查询(比如 a > 10),那么虽然 a 这一列能用到索引,但由于 a 的值已经不固定了,其右侧的 b 列在整个 a > 10 的范围内是无序的。所以,从范围查询那一列开始,后面的索引字段都会失效。
不过在面试中,我经常会碰到一个误区: 有人认为 WHERE b=1 AND a=1 这种写法不符合最左前缀,因为 b 写在了前面。这其实是不对的。MySQL 的查询优化器(Optimizer)会自动调整 WHERE 子句中的条件顺序,使其匹配索引定义的顺序。所以,只要条件里包含了最左列,顺序并不影响索引的命中。
另外,从 MySQL 8.0 开始,引入了“索引跳跃扫描(Index Skip Scan)”,在某些特定场景下(比如左侧列基数很小),即使没有最左列,优化器也可能通过多次扫描索引块来利用索引,但这属于优化器的特例,在设计索引时,我们仍然必须严格遵守最左前缀原则。