为什么 MySQL 选择使用 B+ 树作为索引结构?

为什么 MySQL 选择使用 B+ 树作为索引结构?

一、先明确核心前提:数据库索引的核心需求

数据库索引的本质是加速数据查找,但由于数据库数据通常存储在磁盘(而非内存),所以索引设计必须重点解决两个问题:

  1. 减少磁盘 I/O 次数(磁盘访问速度远慢于内存,是性能瓶颈);

  2. 支持范围查询、排序、分页(业务中最常见的查询场景)。

二、B+ 树的核心特性(为什么适配这些需求)

B+ 树是 B 树的变种,结构上有明确的分层设计,核心特性如下:

1. 层级低,磁盘 I/O 少(最核心原因)

  • B+ 树是多路平衡查找树(而非二叉树),一个节点可以存储多个关键字和子节点指针。

    例如,一个磁盘页(默认 16KB)能存上百个关键字,这使得 B+ 树的高度极低(通常 3-4 层就能存储千万级数据)。

  • 对比:红黑树(二叉树)存储千万级数据时,高度约 30 层,意味着查找需要 30 次磁盘 I/O;而 B+ 树仅需 3-4 次,性能差距巨大。

2. 数据都在叶子节点,查询效率稳定

  • B+ 树的非叶子节点只存关键字和指针,不存数据,叶子节点才存储完整数据(或数据的行指针);

  • 所有叶子节点通过双向链表连接,且按关键字有序排列;

  • 无论查找哪个数据,都需要遍历到叶子节点,因此查询效率稳定(B 树的非叶子节点也存数据,不同数据的查找路径长度可能不同)。

3. 完美适配范围查询 / 排序 / 分页

  • 叶子节点的双向链表是有序的,执行 WHERE id BETWEEN 100 AND 200ORDER BY idLIMIT 100 OFFSET 200 时,只需找到范围的起始节点,然后沿链表遍历即可,无需回溯;

  • 对比:B 树无链表连接,范围查询需要多次回溯父节点;哈希表仅支持等值查询,无法做范围查询。

4. 空间利用率更高

  • 非叶子节点只存关键字和指针,不存数据,因此单个节点能容纳更多关键字,进一步降低树的高度,减少 I/O 次数;

  • 对比:B 树的非叶子节点存数据,单个节点能存的关键字更少,树更高。

三、与其他候选结构的对比(为什么不选其他)

表格

数据结构

优点

缺点(为什么不选)

哈希表

等值查询速度极快(O (1))

不支持范围查询、排序;无法利用索引排序;哈希冲突会降低性能

红黑树

有序,插入 / 删除效率高(O (logn))

二叉结构导致树高过高,磁盘 I/O 次数多;不适合海量数据

B 树

多路平衡,减少 I/O

非叶子节点存数据,空间利用率低;无链表,范围查询效率低;查询效率不稳定

四、MySQL 对 B+ 树的优化(更贴合实际场景)

MySQL 存储引擎(如 InnoDB)还对 B+ 树做了针对性优化:

  1. 聚簇索引:InnoDB 的主键索引叶子节点直接存储整行数据,无需回表,进一步减少 I/O;

  2. 页缓存:将常用的 B+ 树节点(磁盘页)缓存到内存,减少磁盘访问;

  3. 自适应哈希索引:对高频等值查询的索引,自动构建哈希索引,兼顾等值查询和范围查询。

总结

MySQL 选择 B+ 树作为索引结构的核心原因可总结为 3 点:

  1. 低 I/O 成本:多路平衡结构降低树高,大幅减少磁盘 I/O 次数(适配磁盘存储的瓶颈);

  2. 场景适配性强:叶子节点有序且双向链表连接,完美支持范围查询、排序、分页(贴合业务高频需求);

  3. 效率稳定 + 空间利用率高:所有查询都遍历到叶子节点,效率稳定;非叶子节点仅存关键字,空间利用率更高。

这也是为什么 B+ 树成为关系型数据库索引的 “事实标准”,而非其他数据结构。

自托管记账工具(ezBookkeeping) 2026-01-24
Java 中的垃圾回收算法 2026-03-03

评论区