如何遵循最左前缀原则_mysql联合索引优化

1次阅读

最左前缀原则要求联合索引查询必须从最左列开始连续使用:如索引(name,age,dept),仅name、name+age、全列可用;跳过左列或断层则后续列失效;范围查询后列不参与查找但可能覆盖;排序分组也需满足该原则。

如何遵循最左前缀原则_mysql联合索引优化

最左前缀原则是 mysql 联合索引生效的核心规则:查询条件必须从联合索引的最左侧列开始,且连续使用,才能有效利用索引。

什么是联合索引的最左前缀

假设你创建了联合索引 INDEX idx_name_age_dept (name, age, dept),那么以下查询能用上该索引:

  • WHERE name = ‘张三’(只用第1列)
  • WHERE name = ‘张三’ AND age = 25(用第1+2列)
  • WHERE name = ‘张三’ AND age = 25 AND dept = ‘技术部’(全列都用)

但这些写法无法使用该联合索引的全部能力

  • WHERE age = 25(跳过 name,索引失效)
  • WHERE dept = ‘技术部’(只用最右列,不满足最左)
  • WHERE name = ‘张三’ AND dept = ‘技术部’(中间缺失 age,断层,dept 无法走索引)

等值查询 + 范围查询的边界要小心

在联合索引中,一旦出现范围查询(>、等),其右侧所有列都无法用于索引查找(但仍可用于索引覆盖)。

例如索引 (a, b, c)

  • WHERE a = 1 AND b > 10 AND c = 5 → 只有 a 和 b 走索引查找,c 不参与查找(但若 select 中只有 a/b/c,仍可能走覆盖索引)
  • WHERE a > 1 AND b = 2 → 只有 a 走索引查找,b 完全失效(不能跳过 a 直接筛 b)

排序和分组也受最左前缀约束

ORDER BY 或 GROUP BY 要利用联合索引避免 filesort,也必须满足最左前缀:

  • ORDER BY name, age ✅ 可走索引排序
  • ORDER BY name ✅ 可走
  • ORDER BY age ❌ 无法利用索引排序
  • ORDER BY name, dept ❌ 中间跳过 age,dept 不连续,排序失效

注意:如果 WHERE 已经用到 name = ? AND age > ?,那 ORDER BY dept 就完全无法优化——因为 age 是范围,dept 已不在索引查找路径中。

如何设计更合理的联合索引顺序

把区分度高、经常用于等值过滤的列放左边;范围查询列尽量靠右;排序/分组字段若固定,可考虑放在最后(但需确保前面能走索引)。

常见策略:

  • 高频等值条件列优先(如 user_id、status)
  • 多个等值条件时,按查询频率或基数从高到低排(不一定严格,但有助于减少扫描行数)
  • 把 ORDER BY 字段放在索引末尾,仅当前面所有列都能被 WHERE 充分过滤时才有效
  • 避免冗余索引,比如已有 (a,b,c),通常无需再建 (a,b)
text=ZqhQzanResources