free space map(fsm)是 postgresql 用来记录每个数据页"还剩多少可用空间"的辅助结构。它让 insert / update 能快速找到可复用的页面,避免盲目扩展表文件。
free space map 使用树形结构为每个 heap page 记录一个字节的近似空闲空间等级,让 insert / update 能快速定位可复用页面,避免逐页扫描或不必要地扩展表文件。查看 fsm 内容应优先使用 pg_freespacemap 扩展。
1. fsm 保存在哪里?
每个 heap relation 的存储由多个 fork 组成。假设表的 relfilenode 是 16384:
| 主数据文件(main fork) |
| 空闲空间地图(fsm fork) |
| 可见性地图(vm fork) |
查看各 fork 大小:
select
pg_size_pretty(pg_relation_size('public.test', 'main')) as main_size,
pg_size_pretty(pg_relation_size('public.test', 'fsm')) as fsm_size,
pg_size_pretty(pg_relation_size('public.test', 'vm')) as vm_size;fsm 不是整个数据库共享一个文件,而是每个有需要的 relation 都有自己的 fsm fork。表、toast 表和部分索引访问方法都可能使用各自的 fsm。
2. fsm 记录的是什么?
对于 heap 表,fsm 主要记录每个 heap page 大约还有多少可用空间。例如:
heap page | 剩余空间 |
page 0 | 200 bytes |
page 1 | 3000 bytes |
page 2 | 7000 bytes |
page 3 | 1000 bytes |
如果 postgresql 需要插入一个约 2 kb 的 tuple,就可以通过 fsm 快速定位到 page 1 或 page 2,而不需要依次读取并检查所有 heap page。
3. fsm 为什么能快速查找页面?
fsm 不是简单地把所有 heap page 顺序列出来,而是使用树形结构。可以简化理解成:
7000
/ \
3000 7000
/ \ / \
page 0:200 p1:3000 p2:7000 p3:1000每个父节点保存子节点中的最大空闲空间。查找至少有 2 kb 空间的页面时:
- 从根节点开始
- 选择最大空闲空间不小于 2 kb 的分支
- 一直向下查找,最终定位到具体 heap page
- 读取 heap page,再验证真实空间
如果找不到足够空间,postgresql 通常会扩展表文件,创建新的 heap page。
4. insert 如何使用 fsm?
执行一条简单的插入:
insert into test values (1, 'abc');
大致过程如下:
a[计算新 tuple 所需空间] --> b[查询 fsm]
b --> c[找到可能有足够空间的 heap page]
c --> d[读取并锁定该 heap page]
d --> e{检查真实空闲空间}
e -->|空间足够| f[插入 tuple]
e -->|空间不足| g[更新 fsm,继续寻找]
g --> b
e -->|没有合适页面| h[扩展表文件]5. delete 后空间会立即出现在 fsm 中吗?
通常不会立即完全变成可复用空间。
delete from test where id = 1;
被删除的 tuple 先成为 dead tuple,但它占用的空间暂时不能直接重用——其他持有旧快照的事务可能仍然需要看到它。
a[delete] --> b[旧 tuple 变成可能死亡的版本]
b --> c[等待不再被任何事务需要]
c --> d[页面剪枝或 vacuum 清理]
d --> e[空间变为可复用]
e --> f[fsm 更新]因此:
delete from test;
不会立刻缩小表文件,也不一定立刻让 fsm 显示出全部空闲空间。执行 vacuum 可以清理 dead tuple 并更新 fsm:
vacuum test;
普通 vacuum 通常只是让空间可供 postgresql 内部复用,不会把整个表文件空间返还给操作系统。
6. update 和 fsm 的关系
postgresql 的 update 实际上会创建一个新的 tuple 版本。
优先情况:新版本能放在原来的 heap page 中,如果满足索引等条件,还可能形成 hot update(heap-only tuple update)。- 这是什么意思?待更新
非优先情况:如果原页面空间不够,postgresql 通过 fsm 查找其他页面:
a[原页面空间不足] --> b[通过 fsm 查找其他页面]
b --> c[将新 tuple 版本写入其他页面]
c --> d[无法形成 hot update]
d --> e[索引可能需要加入新的索引项]7. 如何查看 fsm 内容?
最方便的是使用 pg_freespacemap 扩展。
安装扩展
create extension pg_freespacemap;
查看所有页面的近似可用空间
select * from pg_freespace('public.test');
select *, round(100 * avail/8192, 2) as "freespace ratio" from pg_freespace('test1');结果类似:
blkno | avail |
0 | 1024 |
1 | 4096 |
2 | 8160 |
其中 blkno 是 heap page 编号,avail 是 fsm 认为该页面大约有多少字节可用。
查看指定 heap page
select pg_freespace('public.test', 0);到此这篇关于postrgesql空闲空间地图的文章就介绍到这了,更多相关postrgesql空闲空间地图内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论