加载中...

| 核心规则 | 最左前缀匹配(Leftmost Prefix) |
| 底层结构 | B+ 树,按列顺序多级排序 |
| 失效场景 | 跳过前导列、对索引列用函数(未用函数索引时) |
假设在 (city, age, name) 三列上建了联合索引,那么查询条件中只要从最左边开始连续匹配,索引就能生效:WHERE city = 'Beijing' 可以,WHERE city = 'Beijing' AND age = 25 也可以,但跳过 city 直接写 WHERE age = 25 则用不上这个索引。
原因在于 B+ 树的排序是按列顺序逐级比较的:先按 city 排,city 相同再按 age 排,age 相同再按 name 排。如果第一列没有固定值,后面的列在物理上就是无序的,范围扫描毫无意义。[1]
业界有两条经验:区分度高的列放前面(减少扫描行数);范围查询的列放最后(范围列之后的列在当前查询里用不上索引排序)。例如 WHERE status = 1 AND created_at > '2024-01-01',应该把 status 放前面,因为 created_at 是范围条件,放前面会导致 status 在这次查询里无法利用索引过滤。
MySQL 8.0 引入了函数索引(Expression Index),PostgreSQL 则早在 7.4 就支持,可以对表达式结果建索引,进一步弥补了联合索引无法覆盖计算列的短板。

| 核心规则 | 最左前缀匹配(Leftmost Prefix) |
| 底层结构 | B+ 树,按列顺序多级排序 |
| 失效场景 | 跳过前导列、对索引列用函数(未用函数索引时) |
登录 后参与讨论
暂无讨论,来发表第一条评论吧