You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

疑问

  1. 为何SQL查询返回的pg_table_size和pg_total_relation_size为64KB,而非物理表文件的24KB?
  2. 为何表的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文件的大小由表的历史数据块数量决定:

  1. PostgreSQL不会自动收缩FSM文件,即使表中数据被删除、数据块数量减少,FSM文件会保持在曾经达到的最大尺寸。如果你的表之前有更多数据块,FSM文件被扩展到24KB,后续数据删除后FSM文件不会自动缩小,因此du显示的大小和主表文件一致。
  2. 若表创建后直接插入数据填满3个数据块,PostgreSQL可能会预分配与数据块数量匹配的FSM空间,导致FSM文件实际占用的磁盘空间(24KB)和主表文件相同。

内容的提问来源于Stack Exchange,提问作者Monika Yadav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:52:06