PostgreSQL pg_table_size() 函数使用指南

PostgreSQL pg_table_size() 是一个核心的数据库对象容量度量函数。在 PostgreSQL 中,一张表的数据不仅包括主关系文件(Main Fork),还可能包含用于存储超长超大字段的变长外存表(TOAST Table)、空闲空间映射文件(FSM)以及可见性映射文件(VM)。

pg_table_size() 的职责就是统计目标表本身所消耗的全部直接数据存储空间(包含 TOAST 数据和空间映射),但明确排除任何挂载在该表上的普通辅助索引(Indexes)。这使它成为衡量数据本身膨胀率与纯数据存储成本的绝佳指标。

PostgreSQL pg_table_size() 语法

这里是 PostgreSQL pg_table_size() 函数的标准语法:

pg_table_size(relation)

参数

relation
必需的。目标关系对象的标识符,可以是表的 regclass 名称(例如 'public.users' 或 'orders'),也可以是目标关系在 pg_class 系统表中的对象标识符(OID)。

返回值

返回一个 bigint 整数,表示该表主体占用的物理磁盘字节总数(Bytes):

  • 统计范围涵盖:主表数据文件(Main Fork)、空闲空间映射(_fsm)、可见性映射(_vm),以及该表关联的 TOAST 表及其 TOAST 索引。
  • 如果目标表不存在,将抛出异常;若传入 NULL,则返回 NULL。

PostgreSQL pg_table_size() 示例

以下示例演示 pg_table_size() 的实战使用及与其他尺寸函数的对比。

基础用法:查询单表主体大小

SELECT 
    'orders' AS relation_name,
    pg_table_size('orders') AS bytes_size,
    pg_size_pretty(pg_table_size('orders')) AS readable_size;

输出:

 relation_name | bytes_size | readable_size 
---------------+------------+---------------
 orders        |  148275200 | 141 MB

对比 pg_relation_size 与 pg_table_size

为了透彻理解其口径差异,我们对比查看带有 TOAST 数据的文章表:

-- 创建测试表并插入大文本内容
CREATE TABLE articles (
    id SERIAL PRIMARY KEY,
    title TEXT,
    full_content TEXT
);

INSERT INTO articles (title, full_content) 
VALUES ('PostgreSQL 架构分析', repeat('这是一篇万字核心解析長文...', 1000));

SELECT 
    pg_size_pretty(pg_relation_size('articles')) AS main_fork_only,
    pg_size_pretty(pg_table_size('articles')) AS table_with_toast,
    pg_size_pretty(pg_total_relation_size('articles')) AS total_with_indexes;

输出:

 main_fork_only | table_with_toast | total_with_indexes 
----------------+------------------+--------------------
 8192 bytes     | 40 kB            | 56 kB

可以看到,pg_relation_size() 仅计算了基础主表分块(8192 字节),而 pg_table_size() 准确捕获了溢出到 TOAST 表中的长文本数据,达到了 40 kB。

结论

  • pg_table_size() 是判断表主体数据(含大字段 TOAST)真实物理占用的黄金基准。
  • 当排查表空间迅速耗尽时,如果 pg_table_size() 远大于业务有效数据量,通常意味着发生了严重的行版本堆积或数据膨胀(Table Bloat),需及时执行 VACUUM 治理。
  • 在容量规划中,评估单纯数据清理(DELETE)能够释放的理论上限时,应参考 pg_table_size()。