Skip to Content
面试题库Mysql[面试题] MySQL索引一定遵循最左前缀匹配吗?

[面试题] MySQL索引一定遵循最左前缀匹配吗?

📖 版块 A:知识讲解版 (温故知新)

  • 最左前缀匹配原则:在 MySQL 的联合索引(如 (a, b, c))中,B+Tree 是按照从左到右的字段顺序进行排序的。查询时必须从索引的最左列开始匹配,如果跳过某一列,则该列之后的索引字段将无法利用索引进行范围过滤或精确匹配。

  • 不遵循或“打破”原则的几种特殊情况

    1. 查询优化器自动调整顺序:如果 SQL 里的过滤条件包含了索引的全部或部分前缀,但顺序是乱的(如 b=2 AND a=1),优化器会自动调整顺序以匹配 (a, b) 索引。
    2. 覆盖索引(Index Full Scan):如果查询的字段全部包含在联合索引中,即使没有从最左列开始,优化器也可能选择全索引扫描(Index Scan)而不是全表扫描(Table Scan),因为索引树比数据表小得多。
    3. 索引跳跃扫描(Index Skip Scan):这是 MySQL 8.0 引入的重要特性。当第一列(最左列)的唯一值(Cardinality)较少时,优化器可以跳过第一列,直接利用后面的索引字段进行查询。
    4. 范围查询限制:如果索引是 (a, b, c),查询条件是 a > 1 AND b = 2,那么 a 可以用到索引,但 b 无法利用索引的有序性进行快速定位,因为在 a 范围之后,b 是无序的。

🎤 版块 B:面试实战版 (高手逐字稿)

Q:MySQL 索引一定遵循最左前缀匹配吗?

💬 高手逐字稿

对于这个问题,我的理解是:在 B+Tree 的索引结构下,联合索引在物理逻辑上确实是严格遵循最左前缀排序的。但在实际的执行层面,MySQL 并不一定死板地只在满足最左匹配时才使用索引。

首先,最左匹配的本质是因为 B+Tree 是先按第一个字段排序,在第一个字段相同的情况下再按第二个字段排序。所以,如果你的查询条件直接跳过了第一列,通常情况下是无法进行“索引下推”或二分查找定位的。

但是,在以下三种场景中,我们会看到“不遵循”最左原则的假象:

第一种是“优化器自愈”。很多初学者认为 WHERE b=2 AND a=1 用不到 (a, b) 索引,这其实是误解。MySQL 的查询优化器(Optimizer)会自动调整过滤条件的顺序,使其匹配索引序列,这种情况本质上还是遵循了最左匹配。

第二种是“全索引扫描(Index Full Scan)”。当我们查询的字段全部被索引覆盖(Covering Index)时,即使查询条件没有最左列,比如索引是 (a, b),查询是 SELECT b FROM table WHERE b = 2。这时候优化器发现:虽然不能通过索引快速定位,但直接扫描这棵小索引树比扫描全表数据行(Clustered Index)要快得多。所以它会扫描整棵索引树,执行计划里显示 type 为 index

第三种是重点,即 MySQL 8.0 引入的“索引跳跃扫描(Index Skip Scan)”。这是对最左原则的一个重大突破。当联合索引的第一列区分度很低(比如是性别字段,只有男和女),而后面的字段区分度很高时,即使 SQL 里没有第一列的条件,优化器也可以在逻辑上将其拆分为 SELECT * FROM table WHERE a='男' AND b=2 UNION SELECT * FROM table WHERE a='女' AND b=2。这样即使不带第一列,也能利用到索引提高效率。

这里有一个容易被忽略的边界细节:索引跳跃扫描虽然强大,但它有严格的限制。它要求第一列的唯一值必须很少,如果第一列是自增 ID 这种区分度极高的字段,开启 Skip Scan 的成本反而远高于全表扫描,优化器就会放弃这个策略。

所以总结来说,最左前缀是联合索引的物理排列规则,但在现代 MySQL 优化器下,索引的利用方式已经变得非常灵活了。


最后更新于:
⏱️

登录后开始阅读

当前 MVP 版本只开放邮箱密码登录注册。完成登录后即可进入面试题内容。

还没有账号?先去注册