联合索引字段应按“等值查询字段(高频、区分度高)→ IN字段 → 范围查询字段”从左到右排列,且ORDER BY/GROUP BY顺序须与索引完全一致;OR、前导通配符、函数操作、隐式转换等会导致索引失效;主键无需显式加入联合索引。

联合索引字段顺序怎么排才不白建
字段顺序直接决定索引是否能被 WHERE、ORDER BY、GROUP BY 用上。MySQL 只能从左到右匹配索引字段,中间断了就停——比如索引是 (a, b, c),WHERE b = 1 AND c = 2 完全用不上这个索引。
实操建议:
- 把
=条件的字段放最左边(尤其是高频等值查询字段) - 多个
=条件时,优先放区分度高的字段(比如user_id比status更高) -
IN视为等值条件,可放在等值段末尾;但IN后面不能再跟范围查询(>、BETWEEN等) - 范围查询(
>、<=、BETWEEN)必须放等值字段之后,且只能有一个——它后面的所有字段都无法用于索引查找
哪些场景下联合索引会失效
不是建了就能用。常见失效现象包括:
-
WHERE a = 1 OR b = 2:OR 会让大部分联合索引退化为全表扫描 -
WHERE a = 1 AND b LIKE '%xx':前导通配符导致b字段无法走索引查找 -
WHERE a + 1 = 10:对索引字段做函数或计算,索引失效 -
WHERE a = 1 AND b IS NULL:如果b列允许 NULL,且没在建索引时显式考虑,某些版本优化器可能跳过索引 - 隐式类型转换:
WHERE user_id = '123'(user_id是INT),触发转换后索引可能失效
要不要把主键加进联合索引里
不用。InnoDB 的二级索引叶子节点天然包含主键值,所以 (a, b) 索引其实已经“自带”主键,查出数据后无需回表也能定位行——前提是你要查的字段都在索引中(覆盖索引)。但如果查询需要额外字段(比如 SELECT *),还是得回表。
实操建议:
- 避免冗余包含主键,比如
(a, b, id)——id是多余的 - 如果业务常查
a、b、c三个字段,直接建(a, b, c),让查询走覆盖索引 - 注意:
TEXT、BLOB类型不能做索引字段,也不支持在联合索引中作为非前导列参与排序
EXPLAIN 看不出问题?重点盯这几个字段
EXPLAIN 输出里光看 type: ref 不够,容易误判。真正关键的是:
-
key_len:显示实际用了索引的字节数。比如key_len = 5对应(a, b)中只用了a(假设a是 TINYINT NOT NULL),说明b没参与查找 -
rows:预估扫描行数。如果远大于实际结果集,说明索引没选好或条件写法有问题 -
Extra中出现Using filesort或Using temporary:意味着ORDER BY或GROUP BY没走索引排序,性能隐患大 - 联合索引用于排序时,
ORDER BY字段顺序必须和索引定义完全一致(且方向一致,除非全是DESC),否则失效
复杂点在于:同一个索引,在不同 WHERE + ORDER BY 组合下,可能一半生效一半失效。别只测一个 case。


















