Skip to content

Latest commit

 

History

History
216 lines (138 loc) · 4.32 KB

File metadata and controls

216 lines (138 loc) · 4.32 KB

MySQL 单列索引,联合索引的存储区别?

一、单列索引与联合索引的核心结构差异(B+Tree 视角)

InnoDB 的每一个索引(主键索引、二级索引)本质上都是一棵 独立的 B+Tree

区别在于:

1. 单列索引(single-column index)

B+Tree 的 key = 单一列字段

例如:

CREATE INDEX idx_name ON t(name);

InnoDB 构建的 B+Tree:

key: name
value: 主键ID(主键索引的值)

叶子节点存储:

(name, pk)

特点:

  • key 比较简单
  • 排序方式基于一个列
  • 体积相对更小

2. 联合索引(composite index / multi-column index)

B+Tree 的 key = 按顺序拼接多个列

例如:

CREATE INDEX idx_user ON t(name, age);

InnoDB 构建的 B+Tree:

key: (name, age)
value: 主键ID

叶子节点存储:

(name, age, pk)

关键点:

  • 索引 key 是“按列顺序拼接”后的二进制序列
  • 排序规则:先按 name 排序,相同 name 再按 age 排序
  • 比单列索引占用更多空间
  • 能提高多条件查询效率(最左前缀原则)

二、物理存储结构上的三个重要区别

区别 1:B+Tree 的“key”结构完全不同

单列索引 key = 一个字段

联合索引 key = 多个字段拼接后的排序 key

例如联合索引:

(name, age, create_time)

B+Tree 的排序顺序为:

(name asc, age asc, create_time asc)

这是 InnoDB 固定行为,无法修改顺序。


区别 2:二级索引的叶子节点 payload 不同(数据量差异)

所有 二级索引 的叶子节点都存放:

  • key(单列 key 或多列 key)
  • 主键值(PK)

单列索引叶子节点内容:

(name, pk)

联合索引叶子节点内容:

(name, age, pk)

加入字段越多,叶子节点变大 → 一个 page 能放的记录数变少 → B+Tree 更深 → 性能更差。

面试官会重点问这一点:

为什么联合索引比单列索引更占空间?

因为叶子节点包含更多列。


区别 3:回表路径不同

单列索引: 只能利用一个字段 查询:

WHERE name = 'A' AND age = 20

单列索引 idx_name 会:

  1. 找到 name='A' 的 pk 列表
  2. 再回表取 age
  3. 然后过滤 age=20

成本较高。


联合索引: 已经包含 name + age 不需要回表过滤第二个字段,减少大量 I/O。

这就是为什么:

(name, age)

比单列两个索引 (name)(age) 更高效。


三、联合索引的存储结构如何影响查询?(最左前缀原理来自哪里)

联合索引 (name, age, city) 的 B+Tree 实际结构:

key1: (name, age, city)
leaf: (name, age, city, pk)

排序方式类似:

(name1, age1, city1)
(name1, age1, city2)
(name1, age2, city1)
(name2, age1, city1)

因此可以连续使用的列必须从最左开始匹配。

为什么不能用 age?

因为 tree 是按 name 排序的,age 分布是乱序的。

存储结构决定了:

(name, age) 可以走索引
(age) 不能走索引

最左前缀原则来自 B+Tree key 的排序机制,不是 MySQL 的“语法限制”。


四、实际使用中会问你的“索引结构区别”要点总结

项目 单列索引 联合索引
B+Tree 数量 1 树 1 树
key 结构 一个列 多列拼接形成排序 key
叶子节点 (col, pk) (col1, col2, ..., pk)
空间消耗
能否覆盖 where 多字段 No Yes(最左前缀)
回表
适用场景 单字段过滤 组合查询、排序加速、覆盖索引

五、总结

InnoDB 的单列索引和联合索引本质上都是独立的 B+Tree,只是存储的 key 不同。

单列索引的 key 是一个列;联合索引的 key 是多个列按顺序拼接形成的复合排序键。

因为联合索引的叶子节点包含更多列,所以占空间更大,但可以减少回表并加速复合查询。

最左前缀原则本质上是联合索引的物理排序结构决定的。