PostgreSQL空闲空间映射表FSM(Free Space Map)解析
源码版本:PG13
Free Space Map 是 PostgreSQL 空闲空间高效管理的一种方式。堆表由于频繁的 update, delete,vacuum,会导致页面出现大小不一的空闲空间,FSM 机制能够有效的管理这些空闲空间,当需要一块指定大小的空闲空间时,通过 FSM 机制可以快速查找到。
1. FSM 原理
Category Range
举个例子,假设 1 字节的值为 255,则表示其对应的 page 页面至少有 8164 个字节的空闲空间。这种方式与 clog 使用 2 bit 表示事务状态类似, 但是这种方式有一个致命缺点,就是查找满足指定大小的空间效率低下,需要遍历所有 FSM 页面,直到找到一个满足指定大小的空闲空间。
2. 大根堆二叉树
4
一个 FSM 页面由两部分组成,叶子节点和非叶子节点。由二叉树的原理可知,二叉树的叶子节点与非叶子节点的比例,大约为1:1,即一个 FSM 页面前一半为非叶子节点,后一半为叶子节点,该页面本身即为一个局部的二叉树,有利于快速查询页面内部的叶子节点。
PG 源码中相关的宏定义:
一个 fsm page 能够包含的 node 数量:
一个 fsm page 非叶子节点的数量:
一个 fsm page 叶子节点的数量:
PG 的最大页面数量约为 2^32,3 层二叉树能够表示的最大页面数约为 LeafNodesPerPage^3,默认 8KB 的页面大小,LeafNodesPerPage^3 远大于 2^32,因此 FSM 的二叉树最多 3 层即能满足 PG 的最大页面映射需求。
FSM 文件内所包含的 FSM 页面和 heap 页面的映射关系如下图所示:
- 第 3 层为叶子节点,其从 FSM 的 page 2 开始,页面连续,最多有 LeafNodesPerPage^2 个页面,页面的前半部分为页内局部二叉树的非叶子节点,后半部分为叶子节点,可以将其看作为数组,其 index 表示 heap 表的 page 号,值表示 heap 表的 page 号对应的空闲 cat 值。
- 第 2 层为非叶子节点,其从 FSM 的 page 1 开始,其页面不连续,最多有 LeafNodesPerPage 个页面,页面的前半部分为页内局部二叉树的非叶子节点,后半部分为叶子节点,表示第3层的节点空闲值。可以将其看作为数组,其 index 表示第 3 层节点的 page 号,值表示第 3 层节点的 page 号对应的空闲 cat 值。
- 第 1 层为根节点,其位于 FSM 的 page 0 ,只占用一个页面。页面的前半部分为页内局部二叉树的非叶子节点,后半部分为叶子节点,表示第2层的节点空闲值。可以将其看作为数组,其 index 表示第 2 层节点的 page 号,值表示第 2 层节点的 page 号对应的空闲 cat 值。
3. 源码实现
函数 fsm_logical_to_physical() 能够把 FSMAddress 表示的树状节点逻辑页号转换成物理页号,即逻辑页号与物理页号之间有一个对应关系。
获取父节点:
获取子节点:
4. 查找一个指定 heap 页的剩余空间
5. 查找一个指定大小的空闲空间
(3)调用 fsm_search() 函数,参数为 rel 和 min_cat。函数内部从搜索二叉树根节点 FSM_ROOT_ADDRESS 开始,在一个大循环内,首先找到大于 min_cat 的节点,如果其 level 不是叶子节点,则进入到它的子节点中继续查找,直到找到值大于 min_cat 并且 level 是叶子节点为止。
文章评论