📌 一句话解释:
联合索引只会从最左边的列开始连续匹配,一旦中断,后面的列就不能再用上索引。
🔍 举个例子说明(表结构):
CREATE TABLE user (id INT,name VARCHAR(50),age INT,city VARCHAR(50),PRIMARY KEY (id),INDEX idx_name_age_city(name, age, city) -- 联合索引
);
我们定义了一个三列的联合索引:(name, age, city)
,这是我们要讨论的主角。
✅ 下面来看几个查询是否能命中索引?
查询语句 | 能否用上索引 | 原因说明 |
---|---|---|
SELECT * FROM user WHERE name = '张三' | ✅ 命中 name | 最左前缀第1列,完美命中 |
SELECT * FROM user WHERE name = '张三' AND age = 20 | ✅ 命中 name+age | 最左前缀连续两列命中 |
SELECT * FROM user WHERE name = '张三' AND city = '深圳' | ✅ 只命中 name | 跳过 age,中断了前缀,city 无法用 |
SELECT * FROM user WHERE age = 20 | ❌ 无法命中 | 缺失 name,最左前缀不满足 |
SELECT * FROM user WHERE city = '深圳' | ❌ 无法命中 | 不是从最左的 name 开始 |
SELECT * FROM user WHERE name LIKE '张%' | ✅ 命中 name | 前缀匹配生效 |
SELECT * FROM user WHERE name LIKE '%张' | ❌ 索引失效 | 前缀模糊,索引失效(LIKE %开头) |
🧠 如何理解“中断了最左前缀”?
比如你有索引 (a, b, c)
,那么:
- 你只能匹配:
a
a, b
a, b, c
- 如果你跳过了 a 或 b,比如只用了
c
或b, c
,就相当于中间断了,索引就白建了。
📌 补充知识:最左前缀不仅适用于 WHERE,也适用于:
GROUP BY
ORDER BY
DISTINCT
ON
(JOIN 的连接条件)
例如:
SELECT * FROM user ORDER BY name, age; -- 命中索引
SELECT * FROM user ORDER BY age; -- ❌ 无法用索引排序
为什么不从最左开始查,就无法匹配呢?
比如有一个 user 表,我们给 name 和 age 建立了一个联合索引 (name, age)
。
ALTER TABLE user add INDEX comidx_name_phone (name,age);
联合索引在 B+ 树中是复合的数据结构,按照从左到右的顺序依次建立搜索树 (name 在左边,age 在右边)。
注意,name 是有序的,age 是无序的。当 name 相等的时候,age 才有序。
当我们使用 where name= '张三' and age = '20'
去查询的时候, B+ 树会优先比较 name 来确定下一步应该搜索的方向,往左还是往右。
如果 name 相同的时候再比较 age。
但如果查询条件没有 name,就不知道应该怎么查了,因为 name 是 B+树中的前置条件,没有 name,索引就派不上用场了。
✅ 场景回顾:
我们定义了如下联合索引:
INDEX idx_name_age_city(name, age, city)
🧠 Mermaid 决策图:判断是否命中联合索引
此处显示不出来,可以复制在 Obsidian 查看流程图。
flowchart TDA[查询中是否包含 name?] -->|是| B[是否包含 age?]A -->|否| Z1[索引失效❌]B -->|是| C[是否包含 city?]B -->|否| Y1[使用部分索引(name)✅]C -->|是| X1[使用完整索引(name, age, city)✅]C -->|否| Y2[使用部分索引(name, age)✅]Y1 --> END[查询命中部分索引🎯]Y2 --> ENDX1 --> ENDZ1 --> END
📝 图示说明:
- 如果查询语句从
name
开始,后面的字段按顺序出现,就能逐步命中更多的联合索引列。 - 如果
name
没有出现在 WHERE 中,即使用了age
和city
,也会 直接索引失效。 - 一旦中间字段断了最左前缀链条(例如只查
name + city
,跳过age
),也只能用到前面那一段。
🚀 最左前缀原则总结口诀:
联合索引连着用,断了就失效;
从左到右顺序查,缺谁都不行;
WHERE、ORDER、GROUP 用,记住它最香;
模糊查询 % 开头,索引说拜拜;