共计 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 最左前缀匹配?
上图展示了联合索引在 B+ 树中的存储结构。核心要点:
- 全局有序 vs 局部有序:只有第一列
a是全局有序的,后面的列只在前面列相同的情况下才有有序性。 - 字典类比:想象一本字典,先按 “首字母” 排序,首字母相同再按 “第二个字母” 排序。如果你跳过首字母直接查第二个字母,字典的有序性就失效了。
- 二分查找的前提:B+ 树利用二分查找快速定位,前提是数据有序。跳过前面的列,后面的列无序,二分查找就失效了。
二、最左前缀匹配规则详解

什么是 MySQL 最左前缀匹配?
上图总结了最左前缀匹配的核心规则。具体说明:
- 规则一:必须从最左列开始。
WHERE b = 2缺少最左列a,无法利用索引的有序性,只能全表扫描。 - 规则二:中间不能跳过。
WHERE a = 1 AND c = 3跳过了b,只能使用a列的索引,c无法走索引。 - 规则三:范围查询会 “断后”。一旦出现范围查询(
>、<、BETWEEN、LIKE '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 最左前缀匹配?
上图解释了范围查询 “断后” 的底层原因。核心问题:
- 范围查询筛选出的数据跨越了多个 “组”,后面的列在这些组内分别有序,但整体无序。
- 无法利用 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 > 2,a 放前面 |
| 范围条件放后面 | 避免 “断后” 问题 | create_time 放在联合索引最后 |
| 覆盖常用查询 | 一索引多查询 | 一个 (a,b,c) 可支持 a、a,b、a,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 优化器会自动重排
WHERE条件,程序员不需要关心书写顺序。 - SELECT 列不影响最左前缀:只影响是否使用覆盖索引(
Using index)。 - OR 条件的陷阱:
OR条件通常导致全表扫描,因为无法保证所有条件都能走索引。 - 范围条件也适用:只是后面的列无法走索引,本身还是能用到索引的。
正文完
发表至: 数据
近一天内

