PostgreSQL FSM(Free Space Map) 源码解读
一、FSM设计目的
FSM,即空闲空间管理的设计初衷是为了能够快速找到一个页是否有足够的自由空间用来容纳新增的数据。如果没有这样的页,则分配新页。在PG 8.4版本以后,每个relation有自己独立的的FSM空间(以_fsm后辍的文件)。
fsm文件:
二、FSM原理
FSM总体设计上采用binary tree和High-level两种算法。
1. Binray tree
一个relation的每个heap page 用一个map byte表示,即8位。这也相当于将一个page的空闲空间(map value) 分为256档位。按当前 page size 8K来算, 8K/256=32;即32字节一个档位。
PG只是用来粗略记录每个页的剩余空间,并不会精确记录真实有多少空间可用。
如下图所示:
目前PG 一个relation最大支持2的32次方个page,一个page size 8K 计算,即4G*8k=32T。为了存放这么多块,三层树结构,至少每个FSM page需要1626个slot。
1626*1626*1626>=2^32。
源码中一个relation 最大BlockNumber定义:
一个叶子节点对应一个relation heap page。分支节点代表自己所有子节点中剩余空间的最大值。如:
假设,我们需要94个字节,那么可以算出map value 为:94+31/32=3.90625(算法如下图)。此时查找map value为4的值,先从root节点顶层开始,一直找到底层。
请求空间时map value算法:
以上面的树为例,那么分配之后的树将变成下面的形态。即以冒泡的形式依次修改父节点branch的值。
总结:采用二叉树后,只需要比较下root节点就可以判断此页剩余空间是否满足空间请求。
2. High-level算法
上面的算法假设只有一个FSM page,但是事实上,随着表的增大,FSM 本身也会变大。FSM 树变大后,将会超出一个page 8K的容量。所以这时就引入High-level的算法,
解决FSM跨page的问题。从上面分析得知,一个relation最大可以有2^32次方,即4G个page。如果层数保持在3层,那么至少每层需要1626个slot来存储 heap page的map value值。即,1626*1626*1626>=2^32。事实上一个FSM page可以存储 (8k-page header)/2~=4000 个 heap page的map value。那么三层结构可以存储 4000*4000*400>>2^32个。
所以PG用三层的High-level树来记录一个表是足够的。High-level树跟FSM low level结构相似,只是High-level的叶子节点指向FSM page (Low-level)的root节点。
PG用fsm_set_avail()和fsm_search_avail()封装了自由空间查找功能和FSM page的结构树,使得High-level访问 FSM page看起来像个黑盒。
总结:1.PG在查找空闲时,先比较root,如果申请的map value比root小,则此页能满足,不然申请新heap page。
使用后,修改leaf节点值,以冒泡方式,依次修改父节点以至root节点。
2.VACUUM操作时,修改叶子节点值,再以冒泡方式,依次修改父节点以至root节点。
3.在查找空闲块时,会有锁,尤其是父级page会有share lock;如果是冒泡修改父级page时,会有exclusive lock。
树形结构在查找上有优点;但并发上,这也是这种结构带来的劣势。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30088583/viewspace-1387176/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/30088583/viewspace-1387176/