联合索引字段顺序决定索引命中率与扫描范围,核心是等值查询优先、高区分度且高频过滤字段靠左,范围查询为分水岭使右侧字段失效,需匹配实际查询模式与排序需求。

联合索引的字段顺序不是随便排的,它直接决定索引能否被命中、走多少范围扫描、甚至是否退化为全表扫描。核心原则是:**最常过滤、区分度高、等值查询优先的字段靠左,范围查询(>、
等值条件优先,放最左侧
MySQL的B+树索引按字段顺序逐层排序。只有当左边所有字段都已确定(即等值匹配),才能快速定位到下一层。比如索引 (user_id, status, create_time):
- 能用上全部三列:WHERE user_id = 100 AND status = 'paid' AND create_time > '2024-01-01'
- 只能用上前两列:WHERE user_id = 100 AND status > 'draft' → create_time 不再生效
- 只能用上第一列:WHERE user_id > 50 → status 和 create_time 全部失效
- 完全用不上:WHERE status = 'paid' → 缺少 user_id,无法定位起始位置
高区分度字段不一定放最前,要结合查询模式
区分度(如唯一值占比)影响索引效率,但不能脱离实际查询逻辑。例如用户表中 phone 字段区分度极高,但如果95%的查询都是 WHERE tenant_id = ? AND status = ?,而 tenant_id 是租户隔离字段(值少但必查),那联合索引就该设计为 (tenant_id, status, phone),而不是 (phone, tenant_id, status)——否则绝大多数查询连索引都用不上。
范围查询是“分水岭”,右侧字段全部失效
一旦某个字段用了范围条件,其右边所有字段都无法用于索引查找(但仍可用于排序或覆盖索引)。常见误区:
- 错误:INDEX (a, b, c) + WHERE a = 1 AND c > 10 → b 被跳过,c 无法利用索引定位(因为 b 未定)
- 正确:若常查 a=1 AND b IN (2,3) AND c > 10,可考虑把 b 放 c 前,或拆成两个等值(IN 视为多个等值)
- LIKE 注意:WHERE name LIKE 'zhang%' 可走索引;WHERE name LIKE '%zhang' 或 LIKE '%zhang%' 则无法使用索引前缀
排序和分页也依赖索引顺序
如果查询带 ORDER BY,且排序字段顺序与索引一致,可避免 filesort。例如:
- 索引 (city, age, score),查询 WHERE city = 'Beijing' ORDER BY age, score → 完美匹配,无需额外排序
- 同索引,查询 WHERE city = 'Beijing' ORDER BY score → 仍需 filesort,因为 score 不在 age 后连续位置
- 分页 LIMIT 也受益于此:ORDER BY city, age 配合索引 (city, age) 可高效跳过前N行










