《为什么 MySQL 三层 B+ 树能存两千万条数据?》

为什么 MySQL 一张表几千万行,按主键查一条数据只要几毫秒?

答案就在 MySQL 的索引结构里——B+ 树。

B+ 树长什么样?

这是一张 B+ 树的示意图,它是一个扇出为 3 的简化版本。与二叉树不同,B+ 树可以有非常多的分支。

树里包含三种节点:根节点、非叶子节点和叶子节点。**只有叶子节点存储数据**,根节点和非叶子节点都是索引层,查询时从根节点开始一步步向下索引到叶子节点。叶子节点之间用指针串成链表——这让范围查询非常高效:找到起点后顺着链表一路扫过去就行。

(严格说,上面说的是聚簇索引;二级索引的叶子节点存的是主键值,这个留到下一篇写。)

图里是扇出 3 的简化示意,真实 InnoDB 的扇出约 1170,看下一段。

为什么三层能存千万数据?

因为一个节点不是一条数据,而是一个 16KB 的磁盘页。一个索引项 = 主键 8 字节 + 指针 6 字节 ≈ 14 字节,一页能放下 16KB ÷ 14B ≈ 1170 个索引项。

三层结构就是:

- 根页 1170 个指针 → 1170 个中间页
- 每个中间页再分 1170 个指针 → 1170 × 1170 ≈ 137 万个叶子页
- 假设一行数据约 1KB,一个叶子页能存 16 行:137 万 × 16 ≈ **2190 万行**

所以三层 B+ 树能撑起千万级数据。行更大就长到四层,量级一样。

为什么比 B 树适合磁盘?

磁盘 IO 次数 = 树高,一次 IO 读一页。B+ 树非叶子节点只存键和指针、不存数据,同样 16KB 一页能装更多索引项——同样数据量下树更矮、IO 更少。

而且数据全在叶子、叶子用链表串起来,范围查询顺着链表一路扫就行;B 树的数据散布在所有节点里,范围扫描要反复上下树,IO 多得多。

所以不是 B 树不能范围查,而是查起来慢——B+ 树在磁盘场景全面占优。

总结

回到开头的问题:按主键查一条数据,最多三次磁盘 IO(根页 → 中间页 → 叶子页),三次 IO 就是毫秒级。(实际中根页常驻内存,通常只要 1-2 次 IO。)

面试口径一句话:**B+ 树高度低、叶子链表串联支持范围查询,三层能存千万行**。