联合索引能用上的查询条件长什么样?
只有满足「最左前缀匹配」的 WHERE 条件,才能真正走
INDEX(a, b, c)这类联合索引。不是“包含这些字段就行”,而是必须从最左边开始、连续使用。
a = 1✅ 走索引(只用 a)
a = 1 AND b = 2✅ 走索引(a + b)
a = 1 AND b = 2 AND c = 3✅ 走索引(全列匹配)
b = 2❌ 不走索引(跳过了 a)
a = 1 AND c = 3❌ 只用上 a,c 被跳过,b 没参与 →
b字段无法利用索引排序,
c实际失效
a IN (1,2) AND b = 3✅ 走索引(
IN算等值,仍满足最左前缀)
注意:MySQL 查询优化器会自动调整
WHERE子句中字段顺序(比如把
b = 2 AND a = 1改成
a = 1 AND b = 2),但前提是所有字段都在同一层级且无函数/计算干扰 —— 别依赖它来“救场”,自己写对才是稳的。
联合索引字段顺序怎么排才不翻车?
顺序不是按字母或出现频率排,而是按「选择性」和「查询模式」定:高区分度字段放前面,高频过滤字段靠左,排序/分组字段尽量靠右。
错误示例:INDEX(gender, age)——
gender只有男/女,索引树第一层就分裂成两支,后续
age再怎么细分也意义不大 正确示例:
INDEX(age, gender)—— 先按年龄精细切分,再在每个年龄段里筛性别,B+ 树搜索路径更短 如果常查
WHERE user_id = ? ORDER BY create_time DESC,优先建
INDEX(user_id, create_time),而不是分开两个单列索引
验证选择性:可用
SELECT COUNT(DISTINCT col)/COUNT(*) FROM table粗估;值越接近 1,该列越适合作为联合索引首列。
为什么加了联合索引,EXPLAIN 还显示 type=ALL 或 Using filesort?
EXPLAIN中
type=ALL表示全表扫描,
Extra: Using filesort表示 MySQL 没法用索引完成排序 —— 这两类问题往往不是没建索引,而是索引没被“完整驱动”。
WHERE a = 1 ORDER BY b+
INDEX(a, b)✅ 能避免 filesort
WHERE a = 1 ORDER BY c+
INDEX(a, b, c)❌
c不在索引前缀连续段内,无法利用排序结构,仍 filesort
SELECT * FROM t WHERE b = 2+
INDEX(a, b, c)❌ 最左没匹配,直接退化为全表扫
WHERE a = 1 AND b > 10 ORDER BY c+
INDEX(a, b, c)⚠️
b是范围查询,
c的排序失效(B+ 树中,a 相同、b > 10 的 c 值是无序的)
关键点:范围查询(
>,
, <code>BETWEEN,
LIKE 'abc%')之后的字段,只能用于索引查找,不能用于排序或精确匹配。
什么时候该用联合索引,而不是多个单列索引?
当你的高频查询同时命中多个字段,且存在固定组合时,联合索引几乎总是优于多个单列索引 —— 因为 MySQL 一般一次只用一个索引(除非开启 index_merge,但代价高、不可控)。
SELECT * FROM orders WHERE user_id = 123 AND status = 'paid' AND created_at > '2025-01-01';错:分别建
INDEX(user_id)、
INDEX(status)、
INDEX(created_at)→ 优化器大概率只选一个,其余条件回表过滤,慢 对:建
INDEX(user_id, status, created_at)→ 三条件一次性定位,且若只查这三列,还能覆盖索引(
Extra: Using index) 更优:如果
status只有 3–4 个值,而
user_id是主键级区分度,就把
user_id放最左;再根据实际数据分布微调
别忘了删冗余索引:比如已有
INDEX(a, b, c),再单独建
INDEX(a)或
INDEX(a, b)就是浪费 —— 写入开销白增,优化器还可能选错。
