PostgreSQL pg_table_size()返回异常及FSM文件大小问题咨询
PostgreSQL 表大小与FSM文件大小疑问
环境信息
- PostgreSQL 13
- CentOS 7
物理文件大小
Table file size: # du -sh 16385_vm 8.0K 16385_vm # du -sh 16385 24K 16385 # du -sh 16385_fsm 24K 16385_fsm
SQL查询的表大小结果
testing=# select pg_size_pretty(pg_relation_size('test1')); pg_size_pretty ---------------- 24 kB (1 row) testing=# select pg_size_pretty(pg_total_relation_size('test1')); pg_size_pretty ---------------- 64 kB (1 row) testing=# select pg_size_pretty(pg_table_size('test1')); pg_size_pretty ---------------- 64 kB (1 row)
表结构信息
testing=# \d+ test1 Table "public.test1" Column | Type | Collation | Nullable | Default | Storage | Stats target | Description --------+-------------------+-----------+----------+---------+----------+--------------+------------- id | integer | | | | plain | | name | character varying | | | | extended | | Access method: heap
空闲空间映射(FSM)查询结果
testing=# SELECT * FROM pg_freespace('test1'); blkno | avail -------+------- 0 | 1088 1 | 1120 2 | 3456 (3 rows)
TOAST表大小信息
testing=# select * from pg_class where oid=16385; -[ RECORD 1 ]-------+------ oid | 16385 relname | test1 relnamespace | 2200 reltype | 16387 reloftype | 0 relowner | 10 relam | 2 relfilenode | 16385 reltablespace | 0 relpages | 3 reltuples | 17 relallvisible | 3 reltoastrelid | 16388 relhasindex | f relisshared | f relpersistence | p relkind | r relnatts | 2 relchecks | 0 relhasrules | f relhastriggers | f relhassubclass | f relrowsecurity | f relforcerowsecurity | f relispopulated | t relreplident | d relispartition | f relrewrite | 0 relfrozenxid | 487 relminmxid | 1 relacl | reloptions | relpartbound |
[root@ip-10-15-11-219 16384]# du -sh 16388 0 16388
疑问
- 为何SQL查询返回的
pg_table_size和pg_total_relation_size为64KB,而非物理表文件的24KB? - 为何表的FSM文件大小为24KB,与实际表文件大小相等?
解答
问题1:SQL查询返回64KB的原因
PostgreSQL不同大小统计函数的统计范围和计算逻辑有差异:
pg_relation_size('test1')仅统计主表数据文件的逻辑大小,对应物理文件16385的24KB,和du的结果一致。pg_table_size和pg_total_relation_size会统计表关联的所有文件的逻辑大小总和,包括主数据文件、FSM文件、VM文件:- 主表文件逻辑大小:24KB(3个8KB页面)
- FSM文件逻辑大小:32KB(PostgreSQL预分配了4个8KB页面,因是稀疏文件,
du仅显示实际写入的24KB) - VM文件逻辑大小:8KB(1个8KB页面)
三者总和为24KB+32KB+8KB=64KB,这就是SQL返回64KB的原因。
问题2:FSM文件大小与主表文件相等的原因
FSM文件的大小由表的历史数据块数量决定:
- PostgreSQL不会自动收缩FSM文件,即使表中数据被删除、数据块数量减少,FSM文件会保持在曾经达到的最大尺寸。如果你的表之前有更多数据块,FSM文件被扩展到24KB,后续数据删除后FSM文件不会自动缩小,因此
du显示的大小和主表文件一致。 - 若表创建后直接插入数据填满3个数据块,PostgreSQL可能会预分配与数据块数量匹配的FSM空间,导致FSM文件实际占用的磁盘空间(24KB)和主表文件相同。
内容的提问来源于Stack Exchange,提问作者Monika Yadav
相关产品推荐
相关产品推荐

