什么是 MySQL 最左前缀匹配?

8次阅读
没有评论

共计 2247 个字符,预计需要花费 6 分钟才能阅读完成。

最左前缀匹配原则 是指:联合索引按照定义顺序从左到右依次匹配,查询条件必须从索引的最左列开始,并且不能跳过中间的列。

-- 联合索引
INDEX idx_a_b_c (a, b, c)

-- ✅ 能走索引
WHERE a = 1
WHERE a = 1 AND b = 2
WHERE a = 1 AND b = 2 AND c = 3

-- ❌ 不能走索引
WHERE b = 2              -- 缺少最左列 a
WHERE c = 3              -- 缺少 a 和 b
WHERE b = 2 AND c = 3    -- 缺少最左列 a

为什么要遵守:联合索引的 B+ 树是按照定义顺序构建的,先按第一列排序,第一列相同再按第二列排序,以此类推。跳过前面的列就无法利用索引的有序性。

一句话总结:联合索引像字典排序,必须从左边开始连续匹配,跳过前面的列就像在字典里直接翻 “中间的字”,无法利用有序性。

深度解析

一、联合索引的 B+ 树结构

什么是 MySQL 最左前缀匹配?

什么是 MySQL 最左前缀匹配?

上图展示了联合索引在 B+ 树中的存储结构。核心要点:

  • 全局有序 vs 局部有序:只有第一列 a 是全局有序的,后面的列只在前面列相同的情况下才有有序性。
  • 字典类比:想象一本字典,先按 “首字母” 排序,首字母相同再按 “第二个字母” 排序。如果你跳过首字母直接查第二个字母,字典的有序性就失效了。
  • 二分查找的前提:B+ 树利用二分查找快速定位,前提是数据有序。跳过前面的列,后面的列无序,二分查找就失效了。

二、最左前缀匹配规则详解

什么是 MySQL 最左前缀匹配?

什么是 MySQL 最左前缀匹配?

上图总结了最左前缀匹配的核心规则。具体说明:

  • 规则一:必须从最左列开始WHERE b = 2 缺少最左列 a,无法利用索引的有序性,只能全表扫描。
  • 规则二:中间不能跳过WHERE a = 1 AND c = 3 跳过了 b,只能使用 a 列的索引,c 无法走索引。
  • 规则三:范围查询会 “断后”。一旦出现范围查询(><BETWEENLIKE 'x%'),该列之后的索引列无法被使用。

三、范围查询 “断后” 问题

-- 索引:INDEX idx_a_b_c (a, b, c)

-- ✅ 三个列都能走索引
WHERE a = 1 AND b = 2 AND c = 3

-- ⚠️ 只能使用 a, b,c 无法走索引
WHERE a = 1 AND b > 2 AND c = 3
--            ↑ 范围查询,后面的 c "断了"

-- ✅ 范围查询放在最后,三个列都能利用索引
WHERE a = 1 AND b = 2 AND c > 3

原因分析

什么是 MySQL 最左前缀匹配?

什么是 MySQL 最左前缀匹配?

上图解释了范围查询 “断后” 的底层原因。核心问题:

  • 范围查询筛选出的数据跨越了多个 “组”,后面的列在这些组内分别有序,但整体无序。
  • 无法利用 B+ 树的二分查找特性,只能逐条扫描。

四、最左前缀的实际应用

-- 场景:订单查询,常见查询条件组合

-- 查询模式分析
-- 1. 按用户查订单:WHERE user_id = ?
-- 2. 按用户+状态查:WHERE user_id = ? AND status = ?
-- 3. 按用户+时间范围查:WHERE user_id = ? AND create_time BETWEEN ? AND ?

-- ❌ 错误的索引设计
INDEX idx_status_user_time (status, user_id, create_time)
-- status 区分度低,放在最左边浪费

-- ✅ 正确的索引设计
INDEX idx_user_status_time (user_id, status, create_time)
-- user_id 区分度高,放在最左边
-- 等值条件在前,范围条件在后

设计原则

原则说明示例
区分度高的列放前面提高索引过滤效果user_id 比 status 区分度高
等值条件放前面保证后面列能走索引WHERE a = 1 AND b > 2a 放前面
范围条件放后面避免 “断后” 问题create_time 放在联合索引最后
覆盖常用查询一索引多查询一个 (a,b,c) 可支持 aa,ba,b,c

五、特殊情况:跳过索引列

-- 索引:INDEX idx_a_b_c (a, b, c)

-- MySQL 5.6+ 的索引下推优化
WHERE a = 1 AND c = 3

-- 没有 ICP:存储引擎返回所有 a=1 的记录,Server 层过滤 c=3
-- 有 ICP:存储引擎直接过滤 a=1 AND c=3,减少回表

-- EXPLAIN 结果
-- Extra: Using index condition(表示使用了索引下推)

注意:虽然 MySQL 5.6+ 有索引下推优化,但这只是在存储引擎层过滤数据,减少回表次数,并不是真正 “走索引”。c = 3 仍然无法利用索引的有序性快速定位。

六、常见误区

什么是 MySQL 最左前缀匹配?

什么是 MySQL 最左前缀匹配?

上图总结了最左前缀原则的常见误区。关键澄清:

  • 条件顺序无关:MySQL 优化器会自动重排 WHERE 条件,程序员不需要关心书写顺序。
  • SELECT 列不影响最左前缀:只影响是否使用覆盖索引(Using index)。
  • OR 条件的陷阱OR 条件通常导致全表扫描,因为无法保证所有条件都能走索引。
  • 范围条件也适用:只是后面的列无法走索引,本身还是能用到索引的。

正文完
 0
数据与人
版权声明:本站原创文章,由 数据与人 于2026-07-02发表,共计2247字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,若要转载请注明出处。
评论(没有评论)