联合索引的最左匹配指mysql只能跳过末尾字段而不能跳过中间字段,本质是b+树逐层排序导致未出现字段后所有列无法定位;可用explain的key和key_len验证是否命中索引。
什么是联合索引的最左匹配?
最左匹配不是“必须从第一个字段查起”,而是指 mysql 在使用联合索引时,**只能跳过末尾的字段,不能跳过中间的字段**。它本质是 b+ 树索引的搜索路径限制:索引按字段顺序逐层排序,一旦某列没出现在查询条件中,后续列就无法利用树结构快速定位。
比如联合索引 (a, b, c),以下条件能用上索引:
-
WHERE a = 1 AND b = 2 AND c = 3(全命中) -
WHERE a = 1 AND b = 2(c 跳过,不影响 a、b 的范围扫描) -
WHERE a = 1(b、c 全跳过,仍可用 a 做等值或范围查找)
但这些不行:
-
WHERE b = 2(a 没出现,B+ 树第一层根本没法定位) -
WHERE a > 1 AND c = 3(a 是范围,b 被跳过,c 就失效了)
如何验证某条 SQL 是否命中联合索引?
别靠猜,用 EXPLAIN 看 key 和 key_len 最直接。
-
key显示实际使用的索引名 → 确认有没有走对的联合索引 -
key_len表示用了索引前多少字节 → 对照字段定义反推用了几列(比如INT非空是 4 字节,VARCHAR(50)utf8mb4 是 200 字节) - 注意
type:如果是range或ref,说明有效利用;index或ALL很可能只扫了索引前缀甚至全表扫
示例:EXPLAIN SELECT * FROM t WHERE a = 1 AND c = 3; 如果 key_len 只有 4(仅 a),说明 c 没进索引查找路径。
联合索引字段顺序怎么排才合理?
顺序不是按字母或字段长短排,而是按 **过滤性 + 查询模式** 综合判断。
- 高选择性字段(如用户 ID、订单号)放前面,能更快缩小数据集
- 经常单独作为查询条件的字段,优先靠左(否则它自己就用不上索引)
- 范围查询字段(
>,BETWEEN,LIKE 'abc%')尽量放右,因为它右边所有字段都会失效 - 排序或分组字段(
ORDER BY,GROUP BY)如果和查询条件共用索引,也要考虑位置是否匹配执行计划
错误例子:(status, create_time),如果常查 WHERE create_time > '2024-01-01',那 create_time 必须放左边,否则这个条件完全走不上索引。
为什么 WHERE a = 1 OR b = 2 用不了联合索引?
因为 OR 会让优化器放弃走索引合并(除非明确配置开启且代价低),更倾向全表扫描或单字段索引。联合索引本身不支持跨列的“并行”匹配。
- MySQL 默认对
OR条件不会拆解为两个索引分别查再合并(index_merge是例外,但不可控且开销大) - 即使有
(a, b)索引,a = 1 OR b = 2也无法同时利用两列的有序性 - 替代方案:拆成两个查询用
UNION ALL,或确保其中一列有独立索引
真正容易被忽略的是:很多业务代码里把多个条件拼成 OR 是为了“兼容性”,但代价是彻底丢掉联合索引优势——这种写法在高并发或大数据量下会突然变慢,且 EXPLAIN 里看不出明显异常,只显示 type: ALL 或 key: NULL。










