联合索引必须从最左字段开始使用,因为其底层B+树仅按第一个字段全局排序,后续字段仅在前序字段值相同时局部有序,跳过最左字段将导致无法定位查找起点,索引完全失效。

联合索引为什么必须从最左字段开始用
因为 InnoDB 的联合索引底层是一棵 B+ 树,而这棵树只按第一个字段排序构建。比如 (name, age, city) 索引,B+ 树先按 name 升序排,name 相同时再按 age 排,最后才是 city。所以 age = 25 单独查,或 city = 'Beijing' 单独查,根本找不到入口——树里压根没按它们建序。
常见错误现象:EXPLAIN 显示 type: ALL 或 key: NULL,明明建了联合索引却没走。
- 跳过最左字段(如只用
age或city)→ 索引完全失效 - 最左字段用了等值(
=或IN),中间字段也用等值 → 后续字段可继续走索引 - 最左字段用了范围(
>、、<code>BETWEEN、LIKE 'abc%')→ 匹配到此为止,右边字段全部失效
WHERE 条件顺序写错,索引还有效吗
MySQL 优化器会自动重排 WHERE 子句顺序,所以 WHERE age = 18 AND name = 'Tom' 和 WHERE name = 'Tom' AND age = 18 对 (name, age) 索引效果一样。但这不等于可以随意写——条件顺序不影响是否走索引,但影响你对索引设计的判断和后续维护成本。
容易踩的坑:依赖优化器“帮你修”会掩盖设计缺陷。比如你建了 (status, create_time),却总写 WHERE create_time > '2025-01-01' AND status = 'active',虽然能走索引,但 create_time 是范围,实际只用上 status,create_time 字段被截断,性能不如把 status 放最左。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 优化器重排只解决“语法顺序”,不改变“匹配路径”
- 写 SQL 时仍应按索引定义顺序组织条件,便于自检和团队协作
- 如果发现
EXPLAIN中key_len比预期小(如索引 3 列但只显示用了 1 列),说明中间有字段因范围/函数/类型隐式转换被跳过
什么时候该把高频过滤字段放最左
不是“哪个字段 select 多就放左边”,而是“哪个字段筛选度高、且常用于等值查询,就放最左”。比如用户表有 status(只有 active/inactive)、region_id(几十个值)、user_id(唯一),查询多为 WHERE status = 'active' AND region_id = 123,那 status 放最左反而不好——它区分度太低,B+ 树第一层节点太多,定位效率差;换成 (region_id, status) 更合理。
性能影响明显:最左字段区分度低会导致索引树层级变深、单次查询扫描更多叶子节点。
- 优先选区分度高(cardinality 高)的字段,如
user_id、order_no、email - 等值查询频率高的字段优于范围查询字段
- 避免把
datetime类型字段放在最左,除非它几乎总是用=精确匹配(极少场景)
覆盖索引怎么配合最左匹配一起用
覆盖索引的本质是让查询所需所有字段都在索引中,避免回表。但它依然受最左匹配约束。比如索引是 (a, b, c),SELECT a, b FROM t WHERE a = 1 AND c = 3 不会走覆盖——因为 c 跳过了 b,索引只匹配到 a,b 和 c 都不在有效范围内,自然无法覆盖。
真正能触发覆盖的典型组合:SELECT a, b FROM t WHERE a = 1 或 SELECT a, b, c FROM t WHERE a = 1 AND b = 2。只要满足最左连续,且 SELECT 的字段全在索引里,Extra 就会显示 Using index。
-
SELECT *几乎不可能走覆盖索引(除非索引包含所有列,不现实) - 联合索引字段顺序决定覆盖能力,不是字段存在就行
- 如果业务需要
SELECT a, c,但经常WHERE a = ? AND c = ?,与其强行用(a, b, c),不如建(a, c)索引——更窄、更快、还能覆盖

















