尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

relly 槽页布局:数据库页面内部的存储结构完全解析

relly 槽页布局:数据库页面内部的存储结构完全解析 relly 槽页布局数据库页面内部的存储结构完全解析【免费下载链接】rellyRDBMS のしくみを学ぶための小さな RDBMS 実装项目地址: https://gitcode.com/gh_mirrors/re/rellyrelly 是一个用于学习 RDBMS 工作原理的微型数据库实现它以极其精简的 Rust 代码演示了存储引擎的核心机制。而**槽页布局Slotted Page Layout**正是 relly 存储层中最关键的底层设计——它决定了 4096 字节的数据库页面如何组织、如何管理空闲空间、如何在 B 树中存放键值对。本文将从零开始带你彻底看懂 relly 槽页布局的内部存储结构、头部字段、槽指针与数据区的协作方式以及它在叶子页和分支页中的复用技巧让你对数据库页面内部结构建立起完整的认知。什么是槽页布局为什么数据库页面需要它在深入了解 relly 槽页布局之前先弄清一个基础问题数据库为什么要把页面划分成槽当我们往表中插入一条记录时记录长度可能每次都不一样比如变长的字符串字段。如果从页头开始顺序存放删除中间一条记录后就会出现空洞后续插入又很难复用这些碎片空间。槽页布局的核心思路是把页面分成两个相向生长的区域——从页头向上生长的槽指针数组和从页尾向下生长的数据区。指针记录每条数据的起始偏移和长度数据本体则紧贴页尾存放。这样无论数据如何增删都能通过指针精确寻址页面满时自然触发 B 树分裂。relly 在 slotted.rs 中用约 150 行代码实现了这一经典结构配合 disk.rs 中定义的PAGE_SIZE 4096构成了整个存储引擎的地基。一图看懂 relly 槽页布局的内存结构relly 的页面是固定 4096 字节的字节数组见 disk.rs 中的PAGE_SIZE槽页布局将其划分为三个部分偏移 0 --------------------------- | Headernum_slots (2字节) | | free_space_offset (2字节) | | pad 填充 (4字节) | ← 共 8 字节 --------------------------- | Pointer[0] (offsetlen) | ← 槽指针数组从页头向上生长 | Pointer[1] (offsetlen) | | Pointer[2] | --------------------------- ← free_space_offset 指向空闲区起点 | 空闲区域 | | (可分配空间) | --------------------------- | 数据 3 | ← 数据区从页尾向下生长 | 数据 2 | | 数据 1 | 页尾 4095 ---------------------------数据区紧贴页尾槽指针数组紧贴页头两者相向生长中间的空闲区域就是可分配空间。这是数据库页面内部存储结构的经典设计也是relly 槽页布局最核心的骨架。relly 槽页头部结构num_slots 与 free_space_offset 如何协同工作槽页布局的头部只有 8 字节定义在 slotted.rs 中pub struct Header { num_slots: u16, // 当前槽的数量 free_space_offset: u16, // 空闲区域起始偏移 _pad: u32, // 对齐填充 }这两个字段是relly 槽页布局的大脑num_slots槽数量记录当前页面上存放了多少条数据槽也就是 slot 数组的长度。free_space_offset空闲空间偏移指向空闲区域的起点即下一个数据应该放置的位置。关键公式是free_space free_space_offset - 指针区大小也就是空闲空间等于数据区顶部减去指针区顶部。头部在initialize时把num_slots置 0、free_space_offset置为页尾此时整页都是空闲区。槽指针 Pointer4 字节精确定位一条数据数据区的每条记录都对应槽数组中的一个 4 字节指针见 slotted.rspub struct Pointer { offset: u16, // 数据起始偏移 len: u16, // 数据长度 }offset数据在页面中的起始位置len数据长度配合 offset 即可算出数据区间[offset, offset len)。读取第 i 条数据时先通过Pointer[i]拿到偏移和长度再从数据区切片取出内容。正因为有了这层间接寻址插入、删除、扩容时只需调整指针数据本体可以随意移动这就是槽页布局最大的灵活性来源。一次完整的插入relly 槽页布局的空闲空间分配流程理解了结构来看 slotted.rs 中insert的完整流程这也是理解数据库页面内部存储结构的经典场景检查空间先判断free_space() 指针大小 数据长度空间不足则返回None由上层触发 B 树节点分裂腾出数据区free_space_offset - len把空闲区起点向页头方向收缩相当于在数据区顶部预留了新数据的位置登记槽位num_slots 1并把新指针插入槽数组的指定位置写入指针新指针的offset指向新的空闲区起点len记为数据长度。之后调用方把数据字节拷贝到该指针指向的区域即可。整个插入是 O(n) 的涉及指针移动但对学习型数据库来说足够清晰直观。真实插入测试可以运行示例 btree-create.rs 感受一下。删除与调整remove 与 resize 的碎片处理思路槽页布局的优势在删除和扩容时体现得尤为明显。删除remove先调用resize(index, 0)把该槽数据长度清零再把后续的指针整体前移最后num_slots - 1。由于数据区是从页尾生长的删除一条数据后在数据区顶部形成的空洞会在下次插入时被顶掉——free_space_offset直接覆盖到空洞之前天然完成了碎片回收无需额外的整理操作。扩容resize当一条记录变大时从空闲区顶部开始整体搬移数据copy_within同时更新所有 offset 小于等于原位置的数据指针最后修改目标指针的len。可以看到relly 槽页布局用最朴素的方式实现了紧凑的存储管理没有任何复杂的碎片整理算法。从槽页到 B 树叶子页与分支页如何复用同一布局relly 槽页布局并不只服务普通表数据它被 B 树的所有节点页面复用形成了完整的数据库页面内部存储层次叶子页leaf.rs在槽页之上增加了 16 字节头部——prev_page_id和next_page_id用于把叶子节点串成双向链表方便范围查询时顺序遍历槽中存放的是用 bincode 序列化后的(key, value)键值对。分支页branch.rs头部只有一个right_child字段槽中存放(key, child_page_id)对用于在树中向下定位。节点标识node.rs在最外层用 8 字节node_type标记页面类型LEAF 或BRANCH 读取时据此分发到不同的解析逻辑。整个页面结构可以这样串起来----------------------------- | node_type (8 字节) | ← 叶子 or 分支 ----------------------------- | 叶子: prev/next_page_id | | 分支: right_child | ← 各节点自己的头部 ----------------------------- | Header(num_slots, free...) | ← 槽页布局头部 | Pointer 数组 | | 空闲区 | | 数据区 (序列化的键值对) | -----------------------------而树的元信息根节点页面号则单独放在一个 meta 页中meta.rs表操作入口在 table.rs 中B 树的插入与分裂逻辑集中在 btree.rs。想快速验证整体效果可以运行 table-create.rs 和 table-index.rs 这两个示例。槽页布局的优缺点从 relly 中学到什么✅ 优点支持变长记录数据长度不受限制删除后空间自动回收不产生永久碎片指针间接寻址数据搬移时不需要改上层引用实现极简适合学习数据库页面内部存储结构的入门者通读。⚠️ 局限数据区只从页尾生长如果频繁在中间插入指针移动开销较大指针数组与数据区共享页空间无法处理超过半页的超大记录relly 通过max_pair_size做了限制超出会触发节点分裂没有页内空闲空间链表空间不足时只能向上层报告并分裂页面。总结吃透 relly 槽页布局你就掌握了数据库页面的设计精髓relly 槽页布局用 8 字节头部 4 字节指针的最小成本解决了数据库页面内部存储结构中最核心的两个问题变长数据的组织与碎片空间的管理。它不仅是 relly 所有表、索引、B 树节点的共同地基也是你理解 MySQL InnoDB、PostgreSQL 等商业数据库页内结构的最佳入门起点。建议你在本地克隆https://gitcode.com/gh_mirrors/re/relly后重点研读 slotted.rs 的单元测试——它用一段 128 字节的页面演示了插入、删除、扩容的完整过程跑通它你就真正读懂了槽页布局的每一个字节。【免费下载链接】rellyRDBMS のしくみを学ぶための小さな RDBMS 実装项目地址: https://gitcode.com/gh_mirrors/re/relly创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表