为什么 MySQL 索引选 B+ 树?

想象一下,你有一本 1000 万页的字典(数据库表),你想查一个字(一行数据)。
如果你一页一页翻(全表扫描),大概要翻到明年。
你需要一个目录(索引)。
但在计算机的硬盘上,设计这个“目录”非常有讲究。因为硬盘读写很慢,我们必须设计一种数据结构,让我们用最少的次数,就能找到数据。
最终,B+ 树 击败了所有对手,成为了关系型数据库(MySQL, Oracle, SQL Server)的绝对霸主。
💻 一、技术分析:让树“变胖”的智慧
B+ 树的核心设计哲学只有两个字:矮、胖。
1. 它是怎么“变胖”的?
- 多路平衡 (Multi-way):
- 普通的二叉树(Binary Tree),一个节点只能分 2 个叉。如果要存 1000 万数据,树会变得非常高(几十层)。
- B+ 树的一个节点,可以分出 1000 个叉!
- 它像一只巨大的章鱼,头伸出 1000 只手,每只手又抓着 1000 只小手。
2. 只有 3 层高?
由于它太胖了(扇出 Fan-out 很大),它的高度惊人地低。
- 第 1 层: 1 个节点(存 1000 个指路牌)。
- 第 2 层: 1000 个节点(存 万个指路牌)。
- 第 3 层: 100 万个节点(存 亿行数据)。
- 结论: 哪怕你要存 10 亿 条数据,B+ 树也只需要 3 层。这意味着从硬盘找数据,最多只需要 3 次 IO。
3. B+ 树的“独门绝技”
相比于它的兄弟 B 树,B+ 树做了两个关键改良:
- 非叶子节点不存数据:
- 树干和树枝上(内部节点)只存索引(Key),不存具体数据(Value)。
- 好处: 节点变得很“轻”,一个 16KB 的内存页能塞下更多的索引。让树变得更胖、更矮。
- 叶子节点手拉手:
- 所有的数据都存在最底层的叶子节点上。
- 而且,所有叶子节点用双向链表连在了一起。
- 好处: 极其适合范围查询(Range Scan)。
- 比如查
ID > 100的人,只要找到 ID=100 的节点,然后顺着链表往后拉就行了,不用回过头去遍历树。
📚 二、故事场景:图书馆的“超级检索术”
为了搞懂为什么不用其他树,我们将 数据库 比作 国家图书馆。
1. 挑战:二叉树/红黑树 (Binary Search Tree)
- 场景: 图书馆的管理员是个瘦高个。
- 规则: 他每次只能把书架分成左右两半。
- 过程: 找一本书,他先问第 1 层管理员,再去第 2 层… 即使平衡得很好,找 1000 万本书也要问 24 个 管理员(树高 24 层)。
- 代价: 每问一个管理员都要跑一次腿(磁盘 IO)。太慢了!
2. 挑战:哈希表 (Hash)
- 场景: 图书馆用瞬移魔法。
- 规则: 你算出一个哈希值,直接瞬移到那本书面前。速度是 ,快得离谱。
- 缺陷:
- 如果你问:“帮我把 ID > 50 的书全拿出来。”
- 魔法失效了。哈希表的数据是散乱分布的,没有顺序。你只能全馆大搜查。
- 结论: 适合 Redis(点对点查询),不适合 MySQL(经常要范围查询
BETWEEN,>,<)。
3. 胜利者:B+ 树
-
场景: 图书馆采用**“部门经理制”**。
-
结构:
-
总经理 (Root): 手里只有一张纸,写着 1000 个部门经理的名字和负责的 ID 范围。
-
部门经理 (Internal): 每个人管 1000 个柜台。
-
柜台 (Leaf): 存放真正的书籍,而且柜台之间有传送带连着。
-
找书:
- 找总经理 -> 锁定部门经理 A。
- 找部门经理 A -> 锁定柜台 B。
- 去柜台 B -> 拿到书。
- 范围查询: 如果要找“这本书后面的 10 本”,直接在柜台 B 顺着传送带拿就行,不用再回去找经理了。
🥊 三、巅峰对决:B+ 树 vs B 树
这是面试最容易混淆的点。为什么 MySQL 选 B+ 而不是 B?
-
B 树 (B-Tree):
-
特点: 数据散落在树的每一层。总经理办公室里也堆满了书,经理办公室里也堆满了书。
-
缺点: 因为办公室被书(数据)占满了,能放的“指路牌”就少了。树不得不长高,IO 次数变多。
-
缺点2: 范围查询极其痛苦,要在树的各层之间跳来跳去(中序遍历)。
-
B+ 树:
-
特点: 只有最底层的仓库放书。上面的办公室只放“指路牌”。
-
优点: 指路牌极多,树极矮(IO 少)。范围查询直接走链表(快)。
🎯 四、总结:为磁盘而生
B+ 树不是最快的树(内存里红黑树更快),也不是最快的查询结构(哈希表更快)。
但它是最适合磁盘的结构。
它通过增加节点的宽度(胖),来减少树的高度(矮),从而最大程度地减少了那昂贵的磁盘 I/O 操作。
一句话总结:B+ 树就是一个“矮胖子”,而且脚底下装了“滑轮”(链表)。
更多推荐




所有评论(0)