训练营5:请详细描述 MySQL 的 B+ 树中查询数据的全过程

一. 核心总结

MySQL 的 B+ 树索引通过多级节点分层定位数据,核心流程为:从根节点逐层比较键值确定路径,最终定位到叶子节点,利用页目录结构快速检索目标数据行。整个过程结合分层索引、页结构优化与二分查找算法,确保百万级数据的高效查询。

二.分层拆解

1.从根节点定位到叶子节点

起点:B+树根节点

定位:将目标键值与节点内存储的索引键值(如主键)对比,确定数据所在区间

  • 非叶子节点仅存储索引键值和子节点指针,不存储实际数据。 * 通过比较确定相等的键值或大概键值范围的路线逐层前往下一个节点

终点: 最终定位到叶子节点,叶子节点存储完整的数据行;B+树高度通常为3~4层 ,保证查询复杂度为 O(log N)

详细流程图:

2.每行节点的数据存储与页结构

页大小:每个节点都对应一个物理页,一页大小是16KB(16*1024B)

数据存储行:

text
复制代码
- 一页可以存放多行数据,假设1行数据为1KB,那么一页可以存储16KB/1=16行 - 每行按主键顺序排列,通过单向链表串联,支持顺序访问。</font>

页目录结构:

分组机制:页目录将数据行划分为多个组,每组包含 1-8 条记录。 分组规则: 第一个分组:仅 1 条记录(最小主键)。 中间分组:4-8 条记录。 最后一个分组:1~8 条记录。 槽位:每个槽位指向组内的最大主键记录(即该组的右边界)

3.页目录的二分查找流程

二分法定位槽:

  • 初始化:low=0(首个槽),high=4(假设共 5 个槽,找主键3)。
  • 中间槽计算:mid=(low+high)/2=2,定位到槽 2 对应的主键4。
  • 比较键值:4 > 3,调整high=2,继续查找左半区。
  • 下一轮中间槽:mid=(0+2)/2=1,定位到槽 1 对应的主键2。
  • 比较键值:2 < 3,调整low=1。
  • 最终定位:high-low=1,确定主键 位于槽 1 和槽 2 之间,实际属于槽 1 的右邻组。

组内遍历:从槽 1 指向的记录(主键)开始,沿链表向后遍历,直到找到主键 3。

三.口语回答

首先,MySQL 的 B+ 树索引通过多级节点分层定位数据,核心流程为:从根节点逐层比较键值确定路径,最终定位到叶子节点,利用页目录结构快速检索目标数据行。

其次,B+树是自平衡树,每个叶子节点到根节点的路径长度相同,而B+树通常为3~4层;

这里我们分为根节点,中间节点,叶子节点展开分析:

数据从根节点找起,每一层通过比较键值定位下一层指针;

每个节点都有一个物理页,每页大小为16KB,每页都有一个页目录。

不管是非叶子节点和叶子节点都是通过页目录来定位的;

页目录将数据分为多个组,组中数据和组之间通过单向链表连接,支持顺序访问;

然后每页通过槽位来定位分组,每个槽位都指向一个组的最大键值;

那数据是怎么通过槽位来定位的呢?

底层采用的是二分法来定位,假设有五个槽位分别有0-8的键值,寻找主键3,那么根据二分法将头分为槽0,尾分为槽4,而二分法的公式是头0+尾4/2,来获取中间值2号槽位,而二号槽位定位到主键4,那么需要再次进行二分,将尾定位到槽2,继续进行公式计算0+2/2=1,定位到1号槽位找到主键2,这时说明主键3在1~2号槽位之间,那么就能根据单向指针向下遍历得到2号槽位的主键3,执行完毕。

四.拓展回答

Q1:你提到了B+树,请你说说你对B+树的理解

A1:首先,从性能,树的高度,范围查询性能来分析;B+树是自平衡树,每个叶子节点到根节点的长度相同,使用B+树进行新增、修改、删除等操作时会进行分裂和合并操作,但它又会有一定的冗余节点,使得删除的时候树结构的变化小,更高效;增删改查的时间复杂读为O(logn),在大量数据的情况下响应速度快性能更高效;B+树每一个节点都有一个物理页,每页的大小为16KB,并且非叶子节点存放的是索引列和指针,这就导致每一页能存放更多的数据,树的结构就比较矮胖 通常为3~4层;然后它的叶子节点通过指针互相连接形成双向链表,数据也是按叶子节点的主键顺序进行存储的,在范围查询时只需要遍历链表,所以它范围查询能力强。

Q2:你提到了B+树一页存放16KB的数据,那么它总共能存放多少数据

A2:B+树每页存放16KB,而它的非叶子节点存放的是指针和索引列,假设叶子节点一行数据为1KB,那么一页就能存放16KB;而中间层存储的是指针和索引列,指针占用6个字节,索引列一般占用8个字节,一共就是8字节,那么中间层节点一共能存放大约1170字节,因为需要将16KB转化为字节,公式这时就为161024/(6+8);同理根节点页是大约1170字节;由此三层总共可以存放11701170*16=21902400,别忘了我们要存放16行数据,所以大约是2000多万条数据;

0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
下载 APP