根节点不存完整行数据!InnoDB B + 树「层级分工 + 索引定位」全拆解

张开发
2026/4/17 14:11:44 15 分钟阅读

分享文章

根节点不存完整行数据!InnoDB B + 树「层级分工 + 索引定位」全拆解
根节点不存完整行数据InnoDB B 树「层级分工 索引定位」全拆解很多第一次学习Mysql数据库索引的朋友都会弄错一个概念那就是认为根节点是用来存完整行数据的这往往是没有弄清楚InnoDB中B树的底层结构所导致的。InnoDB B 树的根节点、非叶子节点都绝对不存完整行数据只有叶子节点才存完整行数据聚集索引。非叶子节点包括根节点只存「索引键 子节点指针」作用是快速定位叶子节点不存业务数据。接下来我会让大家彻底搞懂InnoDB B 树的层级和索引的原理。一、先彻底搞懂B 树每一层到底存什么我们以 InnoDB 的主键聚集索引为例用一个 3 层 B 树的结构首先我们要知道B树依次分为根节点中间节点和叶子节点其中根节点和中间节点可以统称为非叶子节点即B树就由非叶子节点和叶子节点所构成。1. 层级 1根节点最顶层非叶子节点存储内容只存「主键值 子节点中间层的页指针」作用作为整个树的 “总目录”根据查询的主键值快速定位到中间层的对应节点举个栗子根节点存(10, 页A指针)、(30, 页B指针)它的意思是主键 10 的数据去页 A 找10 ≤ 主键 30 的数据去页 B 找主键 ≥30 的数据去页 C 找省略2. 层级 2中间节点非叶子节点树高 2 时存在存储内容同样只存「主键值 子节点叶子层的页指针」作用作为 “二级目录”从根节点定位到中间层后再进一步定位到具体的叶子页举个例子页 A中间节点存(1, 页1指针)、(5, 页2指针)意思是主键 5 的数据去页 1 找主键 ≥5 的数据去页 2 找3. 层级 3叶子节点最底层存储内容完整的行数据所有列并且所有叶子页用双向链表串联作用真正存储业务数据是查询的最终落脚点二、核心问题非叶子节点根节点怎么判断叶子节点存哪些数据1. 核心机制「索引键的分隔值Separator Key」非叶子节点的每一个索引键本质是它右侧子树的「最小主键值」也叫分隔键用来划分数据范围。所有小于当前分隔键的数据都在左侧子树所有大于等于当前分隔键的数据都在右侧子树2. 完整定位流程以查询主键 6 为例根节点判断根节点的分隔键是 10、306 10 → 进入左侧子树页 A中间节点判断页 A 的分隔键是 1、56 ≥5 → 进入右侧子树页 2叶子节点定位页 2 是叶子页直接在页内按顺序找到主键 6 的完整行数据3. 为什么用分隔键就能精准定位因为 InnoDB 的 B 树有两个铁律绝对有序所有节点包括非叶子、叶子内的索引键都严格按升序排列范围划分严格非叶子节点的分隔键会把数据划分成互不重叠的连续区间保证每一行数据只会出现在唯一的叶子页里三、举个完整的 3 层 B 树实例一眼看懂假设我们有一个用户表主键是user_id插入了 1-20 号用户的数据B 树结构如下根节点层 1分隔键user_id子节点页指针数据范围划分7页 A 指针user_id 7 → 页 A15页 B 指针7≤user_id 15 → 页 B-页 C 指针user_id ≥15 → 页 C中间节点层 2以页 A 为例分隔键user_id子节点页指针数据范围划分3页 1 指针user_id 3 → 页 15页 2 指针3≤user_id 5 → 页 2-页 3 指针user_id ≥5 → 页 3叶子节点层 3以页 3 为例user_idnameage...完整行数据下一页指针5张三20...页 4 指针6李四21...页 4 指针7王五22...页 4 指针你看根节点只存 7、15 两个分隔键完全不存用户的 name、age 等完整数据中间节点只存 3、5 两个分隔键也不存完整数据只有叶子页 3 里才存了 5、6、7 号用户的完整行数据。四、补充为什么非叶子节点不存完整数据1. 核心原因最大化扇出降低树高非叶子节点如果存完整数据一个 16KB 的页只能存十几行树会变得 “又高又瘦”查询需要几十次磁盘 IO性能爆炸只存「索引键 指针」总大小仅十几字节一个 16KB 的页能存上千个索引项树变得 “矮胖”亿级数据也只需要 3-4 次 IO2. 额外好处减少内存占用根节点和上层非叶子节点会被 InnoDB常驻内存缓冲池因为查询永远从根节点开始只存小体积的索引键 指针内存占用极低能让更多索引页常驻内存进一步提升查询速度五、面试高频考点根节点会不会分裂树高怎么变1. 根节点的分裂根节点本质也是非叶子节点当根节点存满了16KB 页填满同样会触发页分裂申请一个新的根节点页把原根节点的一半分隔键迁移到新根节点原根节点变成中间节点树的高度 1注意根节点分裂是树长高的唯一方式InnoDB 的 B 树永远从根节点开始生长不会从叶子层直接长高。2. 树高的极限InnoDB 的 B 树高度通常在3-4 层千万 - 亿级数据最多不会超过 5 层树高每增加 1 层查询就多一次磁盘 IO所以 InnoDB 的设计就是通过高扇出把树高压到最低六、最终总结根节点 / 非叶子节点只存「索引键 子节点指针」绝对不存完整行数据定位逻辑通过「分隔键」划分数据范围按层级快速定位到唯一的叶子页叶子节点唯一存储完整行数据的层级所有数据按主键有序排列设计本质用 “目录式” 的非叶子节点最大化扇出、降低树高实现海量数据下的高效查询这是前置内容仅做一些参考学习后面会陆续讲解数据库索引相关的知识欢迎读者大佬指点批评

更多文章