mysql中联合索引的创建与使用方法

7次阅读

联合索引字段顺序不能随便调换,因为B+树按定义顺序逐列排序,必须满足最左前缀匹配才能命中索引;等值查询字段应放最左,高区分度字段优先但需结合查询模式,避免冗余索引。

mysql中联合索引的创建与使用方法

联合索引字段顺序为什么不能随便调换

联合索引的字段顺序直接影响查询能否命中索引,本质是 B+ 树的排序规则决定的。mysql 会按定义顺序逐列构建索引项,(a, b, c) 的索引树先按 a 排序,a 相同时再按 b 排序,a,b 都相同时才按 c 排序。

这意味着只有满足「最左前缀匹配」的条件才能走索引:

  • WHERE a = 1 ✅ 走索引
  • WHERE a = 1 AND b = 2 ✅ 走索引
  • WHERE a = 1 AND b = 2 AND c = 3 ✅ 走索引
  • WHERE b = 2 ❌ 不走索引(跳过 a
  • WHERE a = 1 AND c = 3 ⚠️ 只用到 ac 无法利用(b 缺失导致 c 无序)

如何创建高效联合索引:三个实操原则

建索引不是字段,而是围绕高频查询模式设计。常见误区是把所有 WHERE 字段全塞进去,结果索引大、更新慢、还用不上。

  • 把等值查询字段放最左:例如 WHERE status = 'done' AND user_id = 123 AND created_at > '2024-01-01',应建 (status, user_id, created_at)statususer_id 是等值,created_at 是范围,放最后
  • 高区分度字段优先但不绝对:比如 gender(只有 ‘M’/’F’)区分度极低,即使放最左也难提升效率;但如果查询总是 WHERE gender = 'F' AND city = 'Beijing',且 city 值太多,反而先筛 gender 能快速缩小扫描范围
  • 避免冗余索引:已有 (a, b),再建 (a) 就是冗余;但 (a, b)(a, b, c) 不冗余——后者支持三字段查询,前者不支持

验证联合索引是否生效:看 EXPLaiN 的关键字段

别只看 type 是否为 refrange,重点盯这三个输出:

  • key:显示实际使用的索引名,为空说明没走索引
  • key_len:表示用了索引的多少字节。例如 key_len = 10 对应 (a, b)a 占 4 字节 + b 占 6 字节,说明两列都用上了;若 key_len = 4,大概率只用了 a
  • Extra 中出现 using index 表示覆盖索引(无需回表),出现 Using where; Using index 是理想状态;若出现 Using filesortUsing temporary,说明排序或分组没走索引,可能需要调整索引或 SQL
EXPLAIN SELECT * FROM orders WHERE status = 'shipped' AND user_id = 5566;

什么时候联合索引会“失效”:几个典型陷阱

即使语法正确、字段顺序合理,以下操作也会让联合索引退化为全表扫描或部分失效:

  • 对索引字段做函数操作:WHERE YEAR(created_at) = 2024 → 改成 WHERE created_at >= '2024-01-01' AND created_at
  • 隐式类型转换user_idint,但写成 WHERE user_id = '123'字符串),可能导致索引失效(取决于 MySQL 版本和字符集)
  • 使用 OR 连接非同一索引字段:WHERE a = 1 OR b = 2,除非 ab 分别有单列索引,否则联合索引 (a,b) 无法整体利用
  • LIKE 左模糊:WHERE name LIKE '%abc' 无法用索引;WHERE name LIKE 'abc%' 可以(前提是 name 在联合索引最左或连续前缀位置)

联合索引不是银弹,它的价值高度依赖查询写法和数据分布。上线前务必用真实数据量 + EXPLAIN 验证,而不是只看测试库里几条记录的执行速度。

text=ZqhQzanResources