<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>索引 on 随手记</title><link>https://www.bufio.cn/tags/%E7%B4%A2%E5%BC%95/</link><description>Recent content in 索引 on 随手记</description><generator>Hugo</generator><language>zh-cn</language><copyright>© 2026 &lt;a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener"&gt;苏ICP备2023022553号-1&lt;/a&gt;</copyright><lastBuildDate>Wed, 29 Apr 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://www.bufio.cn/tags/%E7%B4%A2%E5%BC%95/index.xml" rel="self" type="application/rss+xml"/><item><title>MySQL B+ Tree 机制与算法详解</title><link>https://www.bufio.cn/posts/mysql-b-plus-tree-mechanisms-and-algorithms/</link><pubDate>Wed, 29 Apr 2026 00:00:00 +0800</pubDate><guid>https://www.bufio.cn/posts/mysql-b-plus-tree-mechanisms-and-algorithms/</guid><description>&lt;h2 id="为什么数据库普遍选择-b-tree"&gt;为什么数据库普遍选择 B+ Tree&lt;/h2&gt;
&lt;p&gt;如果只从算法课本看，查找一个有序集合有很多选择：数组可以二分，哈希表可以做到平均 O(1)，红黑树、AVL 树可以做到 O(logN)。但数据库的核心问题不是“CPU 内存里怎么找”，而是“磁盘或 SSD 上的数据怎么少读几次”。&lt;/p&gt;
&lt;p&gt;MySQL 的 InnoDB 存储引擎把表数据和索引组织成页。默认情况下，一个页通常是 16KB。一次查询如果每深入一层索引就需要读取一个页，那么树的高度越低，I/O 次数就越少。B+ Tree 的核心优势就在这里：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;每个节点能存放很多 key，树的分叉数很大，高度很低。&lt;/li&gt;
&lt;li&gt;所有真实记录都在叶子节点，非叶子节点只负责导航。&lt;/li&gt;
&lt;li&gt;叶子节点之间按 key 顺序连接，非常适合范围查询和排序扫描。&lt;/li&gt;
&lt;li&gt;节点大小天然适合数据库页，可以和磁盘读写单位对齐。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;所以，B+ Tree 不是为了在理论复杂度上压倒所有结构，而是为了适配数据库最昂贵的资源：随机 I/O。&lt;/p&gt;
&lt;h2 id="从二叉树到-b-tree"&gt;从二叉树到 B+ Tree&lt;/h2&gt;
&lt;p&gt;普通二叉搜索树每个节点最多两个孩子。即使它保持平衡，一千万条数据的高度也大约是二十多层。放在内存里问题不大，放在数据库里就意味着一次查找可能触发很多次随机页读取。&lt;/p&gt;
&lt;p&gt;B Tree 和 B+ Tree 解决的是“分叉太少”的问题。一个节点可以保存多个 key 和多个孩子指针。例如节点中有这些分隔 key：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[10 | 20 | 30]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;它可以把搜索空间分成四段：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;(-∞, 10) [10, 20) [20, 30) [30, +∞)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这样，一个节点不是二选一，而是多路分发。只要一个页中能放下足够多的 key 和指针，树的高度就会非常低。&lt;/p&gt;
&lt;p&gt;B+ Tree 相比 B Tree 又进一步做了一个重要取舍：非叶子节点不存放完整数据记录，只存放用于导航的 key 和子节点页号；所有完整记录都放在叶子节点。这样非叶子节点更小，能容纳更多 key，树也就更矮。&lt;/p&gt;
&lt;h2 id="b-tree-的基本结构"&gt;B+ Tree 的基本结构&lt;/h2&gt;
&lt;p&gt;一棵典型 B+ Tree 可以分成三类节点：&lt;/p&gt;</description></item></channel></rss>