# MySQL 三层 B+ 树能存多少数据?

9 min read
Table of Contents

MySQL 三层 B+ 树能存多少数据?

MySQL 三层 B+ 树能存储多少数据?

【核心定义】

MySQL 三层 B+ 树能存储的数据量,取决于页大小(Page Size)、主键类型(通常是 BIGINT)以及记录行的大小,其本质是计算 B+ 树索引结构在给定层级下的最大数据页容纳能力。

【关键要点】

  1. 计算基础是数据页:InnoDB 存储引擎中,所有数据(包括索引和数据行)都存储在固定大小的页(Page)中,默认大小为 16KB。这是所有容量计算的基石。
  2. 三层结构分布:一个标准的三层 B+ 树包含:
    • 根节点(Root Page):第 1 层,常驻内存。
    • 中间节点(Non-Leaf Pages):第 2 层,存储索引键和指向子页的指针。
    • 叶子节点(Leaf Pages):第 3 层,存储完整的行记录(在聚簇索引中)或索引键与主键(在二级索引中)。
  3. 核心计算公式:
    • 总记录数 ≈ 单页指针数 ^ (树高度 - 1) × 单页记录数
    • 对于三层树(高度=3):总记录数 ≈ 单页指针数² × 单页记录数

【深度推导/细节】

我们以最典型的 聚簇索引(主键索引) 为例,使用 BIGINT 自增主键 和 默认 16KB 页 进行推导。

Step 1: 计算单个非叶子节点(第1、2层)能存放多少指针(索引条目)

  • 一个索引条目主要由 主键字段(BIGINT,8字节) 和 指向子页的指针(6字节) 组成,共约 14字节。
  • 页头、页目录等元信息会占用一部分空间,通常估算时,一个非叶子页大约能存放 1200 个 这样的索引条目(即 16KB / 14B ≈ 1170,取整为便于计算的约数 1200)。
  • 结论:一个非叶子页可以指向大约 1200 个 子页。

Step 2: 计算单个叶子节点(第3层)能存放多少行记录

  • 这完全取决于单行数据的大小。假设我们有一条简单的用户记录:id(BIGINT, 8B), name(VARCHAR(20), 约20B), age(INT, 4B),加上事务ID、回滚指针等行格式开销(约 20-30字节),单行记录总大小估算为 约 1KB。
  • 那么,一个 16KB 的叶子页大约能存放 16 行 记录(16KB / 1KB = 16)。
  • 注意:如果行记录非常小(例如只有几十字节),单页可存放的记录数会显著增加(可能达到数百行)。

Step 3: 计算三层 B+ 树的总容量

  • 根节点(第1层)有 1200 个指针,指向 1200 个中间页(第2层)。
  • 每个中间页(第2层)也有 1200 个指针,各指向 1200 个叶子页(第3层)。
  • 因此,叶子页总数 = 1200 × 1200 = 1,440,000 个。
  • 总记录数 = 叶子页总数 × 单页记录数 = 1,440,000 × 16 = **约 2300 万条**。

核心矛盾与变量分析:

  • 行大小是最大变量:如果单行记录只有 100字节,单页可存约 16KB / 100B ≈ 160 行,总容量将激增至 1,440,000 × 160 ≈ 23 亿条。反之,如果单行记录达到 8KB,则总容量可能只有约 288 万条。
  • 主键类型影响:若使用 INT(4字节) 作为主键,非叶子页的条目更小,单页可容纳的指针数会增加(例如达到约 1800),总容量会进一步提升。
  • 三层是性能与容量的平衡点:三层结构意味着最多只需 3次磁盘 I/O(根节点常驻内存,实际只需2次)即可定位到任何数据,在支撑海量数据的同时保证了优异的查询性能。

【关联/对比】

  • B+树 vs B树:B+树的所有数据都存储在叶子节点,且叶子节点通过指针相连,这使得范围查询和全表扫描效率极高,而B树的数据可能分布在各层。MySQL 选择 B+ 树正是为了优化磁盘I/O和范围查询。
  • 聚簇索引 vs 二级索引:上述计算针对聚簇索引。二级索引的叶子节点存储的是索引键 + 主键值,而非完整数据行,因此其叶子页通常能容纳更多的条目,其三层结构能覆盖的索引条目总数会远高于聚簇索引的数据行总数。
  • InnoDB vs MyISAM:MyISAM 的索引和数据是分开存储的(非聚簇索引),其索引结构的容量计算方式不同,且 MyISAM 不支持事务,页结构更简单。

『面试官追问』

  1. 为什么是1200和16这两个估算数字?

    • 1200 是基于 (16*1024) / 14 ≈ 1170 的工程近似,方便心算和表达。它体现了 索引条目大小 对树“分叉数”(扇出)的决定性影响。
    • 16 是一个假设的 平均行大小 推算出的值,用于强调 实际数据行大小是决定总存储量的最关键因素。面试官可能期望你指出这个变量,并展示如何根据它调整计算。
  2. 如果数据超过这个估算值,树会变成四层吗?

    • 是的,这是 B+ 树的 动态平衡 过程。当叶子节点持续增加,导致根节点和中间节点无法容纳更多指针时,树就会 分裂和增高。从三层变为四层后,最大容量将变为 1200³ × 单页记录数,呈指数级增长。
  3. 页大小可以调整吗?有什么影响?

    • 可以。InnoDB 支持 innodb_page_size 设置为 4K、8K、16K、32K、64K。增大页大小会直接增加单页的指针数和记录数,从而显著提升单层树的承载能力,减少树高。但大页可能造成内部碎片浪费,尤其对于大量小行记录的表。通常保持默认 16KB 是最佳平衡。
  4. 这个“三层”的高度包含叶子节点层吗?

    • 包含。在数据库领域的通用表述中,B+ 树的高度(Height)或深度(Depth)是指从根节点到叶子节点的层级数。因此,“三层 B+ 树”就是指:根节点(L1)、中间层(L2)、叶子层(L3)。有些资料可能从 0 开始计数,但面试中按“三层”理解更普遍。

总结陈述: “因此,对于 MySQL InnoDB 表,在默认 16KB 页大小、使用 BIGINT 主键且单行记录约为 1KB 的典型场景下,一个三层 B+ 树结构的聚簇索引大约能存储 2000万到3000万条 数据。这是数据库表设计时一个重要的参考线,当数据量逼近这个量级时,需要关注索引性能和可能的树高增长。”

My avatar

文章看完了,不打算去别的篇章转转吗?👀 感谢你的耐心阅读!如果你有问题想探讨,或者发现了文中的 Bug,请务必通过页脚的链接联系我


More Posts

# MySQL 事务的二阶段提交是什么?

8 min read

二阶段提交(Two-Phase Commit,2PC)是一种分布式事务协议,用于确保在分布式系统中,多个参与者(如多个数据库节点)的事务要么全部提交,要么全部回滚,从而保证ACID特性中的原子性。

Read

Comments