从零起步学习MySQL || 第十章:深入了解B+树及B+树的性能优势(结合底层数据结构与数据库设计深度解析)

一、什么是 B+ 树?

定义

B+ 树(B Plus Tree) 是一种 多路平衡查找树(Multi-way Balanced Search Tree),常用于数据库和文件系统的索引结构。

它是对 B 树(B-Tree) 的一种改进。

每个节点最多可以有 m 个子节点(m 阶 B+ 树),而不是像二叉树那样只有 2 个。


B+ 树的结构特点

特点总结:

特点 说明
1️⃣ 所有数据都存放在叶子节点 非叶子节点只存键值和指针,不存放实际数据
2️⃣ 叶子节点之间有双向链表 支持顺序和范围查询
3️⃣ 树高较低 即使存百万行数据,树高通常不超过 3~4 层
4️⃣ 节点可存多条索引键 减少磁盘IO次数,提高查询性能
5️⃣ 自动保持平衡 插入/删除后仍能保持平衡结构

二、为什么 MySQL 选择 B+ 树?

我们对比一下常见的几种数据结构

数据结构 查询复杂度 范围查询 磁盘IO效率 说明
二叉查找树(BST) O(logN)(不稳定) 容易退化成链表
AVL树 / 红黑树 O(logN) 只能内存结构,节点太小
B树 O(logN) 一般 内节点也存数据,范围查询不连续
B+树 O(logN) 数据库最常用结构

核心原因:磁盘访问效率 + 范围查询性能

数据库索引存储在磁盘上,而磁盘 I/O 是数据库性能瓶颈。

B+ 树在设计上做了两件事来降低 I/O:

  1. 每个节点可以存多个键(多路分叉)

    ⇒ 树高更低,一次查询需要的磁盘页读取次数更少。

    比如:

    • 二叉树可能需要访问几十次;

    • B+ 树只需 2~3 次磁盘IO就能定位到目标。

  2. 叶子节点链表结构方便范围查询

    ⇒ 只要找到范围起点,一路顺序扫描叶子节点即可完成范围查询。


三、B+ 树在不同操作下的性能表现

单点查询(= 查询)

过程:

  1. 从根节点开始,按键值查找下层;

  2. 每层只需一次磁盘IO;

  3. 到叶子节点后即可找到对应记录。

性能分析:

  • 时间复杂度:O(logN)

  • 树高低(一般 2~4),磁盘IO次数少;

  • 查找效率非常高且稳定。


插入与删除

插入:

  • 先找到目标页;

  • 插入记录;

  • 若页满,则进行 节点分裂(split)

  • 若分裂上溢,则可能向上调整索引(保证平衡)。

删除:

  • 删除记录;

  • 若页太空(低于阈值),可能触发 合并(merge)

  • 仍保持树平衡。

性能分析:

  • 插入、删除复杂度:O(logN)

  • B+ 树能自动维持平衡,不会退化成链表;

  • 分裂/合并成本较低,因为一次操作只影响局部页。


范围查询(BETWEEN / ORDER BY / <, >)

B+ 树在范围查询上远优于B树或红黑树。

因为:

  • 所有数据都在叶子节点;

  • 叶子节点之间通过 双向链表 相连;

  • 只需找到起点叶子节点,然后沿链表顺序遍历即可。

    SELECT * FROM user WHERE id BETWEEN 100 AND 200;

执行过程:

  1. 在B+树中找到 id=100 的叶子节点;

  2. 顺着叶子节点链表一直往后扫,直到 id=200

  3. 中间无需回到父节点查找。

复杂度:O(logN + M)

(logN 定位起点 + M 为结果数量)

这是数据库选择 B+ 树的重要原因之一!


四、MySQL 中的 B+ 树的特点(InnoDB 实现)

MySQL 的 InnoDB 存储引擎对 B+ 树做了特定优化,使之更适合磁盘存储。

1️⃣ 页(Page)为节点单位

  • 每个节点对应一个 页(16KB)

  • 每次磁盘IO加载整个页;

  • 页中存储多个键值(上千个),极大减少树高。

例如:

1000万条记录的表,只需 3~4 层B+树!


2️⃣ 聚簇索引(Clustered Index)

InnoDB 的主键索引是 聚簇索引

  • 叶子节点存储整行数据;

  • 数据文件本身就是B+树结构。

    CREATE TABLE user (
    id INT PRIMARY KEY,
    name VARCHAR(20),
    age INT
    );

📘 聚簇索引B+树结构:

  • 非叶子节点存储主键值 + 子节点指针;

  • 叶子节点存储整行记录。

👉 按主键查找只需一次 B+ 树遍历。


3️⃣ 二级索引(Secondary Index)

  • 叶子节点不存整行数据,只存索引列 + 主键值

  • 查询时若需要整行数据,会先查二级索引,再"回表"到聚簇索引查主键。

示意:

复制代码
idx_name (name -> id)
聚簇索引 (id -> row_data)

二级索引结构:

  • 非叶子节点:索引键 + 指针

  • 叶子节点:索引键 + 主键值(指向聚簇索引)


4️⃣ 叶子节点链表

InnoDB 的B+树叶子节点通过 双向链表 相连:

  • 支持顺序扫描(ORDER BY

  • 支持范围查询(BETWEEN / < / >


5️⃣ 自平衡 + 空间利用率高

  • 每个页16KB,内部多条记录;

  • 节点分裂、合并时保持平衡;

  • 减少磁盘IO,提高查询速度。


总结

对比项 B 树 B+ 树(MySQL采用)
数据存放位置 各层节点 仅叶子节点
叶子节点是否链表连接 是(双向链表)
范围查询性能 一般 优(顺序扫描)
树高 稍高 更低(更多分叉)
查询效率稳定性 一般
MySQL 实现 --- 每个节点为16KB页

一句话总结

MySQL 采用 B+ 树作为索引结构,是因为它能最大化磁盘IO效率,支持高性能的单点查找、插入删除操作,并且天然适合范围查询。

相关推荐
一瓢一瓢的饮 alanchan11 分钟前
Flink原理与实战(java版)#第2章 Flink的入门(第二节Flink简介)
java·大数据·flink·kafka·实时计算·离线计算·流批一体化计算
golang学习记12 分钟前
🍵 Go Queryx 入门指南:让数据库操作像喝奶茶一样丝滑!
后端
vx_bscxy32212 分钟前
告别毕设焦虑!Python 爬虫 + Java 系统 + 数据大屏,含详细开发文档 基于微信小程序的民宿预约系统22398 (上万套实战教程,赠送源码)
java·spring boot·mysql·微信小程序·课程设计
z_鑫32 分钟前
Java线程池原理深度解析
java·开发语言·后端
春生野草36 分钟前
启动Nginx
java·微服务·架构
悟空CRM服务41 分钟前
开源的力量:如何用开源技术构建高效IT架构?
java·人工智能·架构·开源·开源软件
神仙别闹1 小时前
基于SpringMVC+Spring+MyBatis开发的个人博客网站
java·spring·mybatis
小红的布丁1 小时前
Redis存储引擎剖析:从哈希表到智能数据结构
数据库·redis
华仔啊1 小时前
MyBatis-Plus 不只是简化CRUD!资深架构师总结的15个高阶用法
java·后端·mybatis
吴名氏.1 小时前
电子书《ASP.NET MVC企业级实战》
后端·asp.net·mvc·编程语言