PostgreSQL pg_relation_size() 函数使用指南

PostgreSQL pg_relation_size() 是数据库内核运维与磁盘空间精细化分析中最核心的基础度量函数之一。

在 PostgreSQL 的物理存储模型中,一个关系对象(Relation,例如普通表、单一索引、序列或物化视图)可能会在磁盘上切分为不同的“分叉”(Forks):存储主体数据行的主分叉(main)、记录可用空间的空闲空间映射(fsm)、以及优化索引扫描与清理效率的可见性映射(vm)。

pg_relation_size() 允许用户按需测量特定关系对象指定分叉的物理磁盘字节占用量,为深度存储诊断与表膨胀分析提供细粒度支持。

PostgreSQL pg_relation_size() 语法

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

pg_relation_size(relation [, fork])

参数

relation
必需的。目标关系对象的标识符。可以是对象的文本名称(类型为 regclass,例如 'users' 或 'public.orders'),也可以是 pg_class 系统目录中该对象的 OID。
fork
可选的。指定要测量的存储分叉名称(文本类型)。合法选项包括:
  • 'main':主数据分叉(默认值)。测量表的主体堆数据或索引的基础 B-Tree 数据文件。
  • 'fsm':空闲空间映射(Free Space Map)分叉。
  • 'vm':可见性映射(Visibility Map)分叉。
  • 'init':非日志表(UNLOGGED 表)在崩溃恢复时使用的初始化分叉。

返回值

返回一个 bigint 整数,表示指定关系对象该分叉在磁盘上消耗的实际物理字节数(Bytes):

  • 若省略 fork 参数,默认返回 'main' 分叉的大小。
  • 若目标对象不存在,抛出异常;若参数为 NULL,返回 NULL。

PostgreSQL pg_relation_size() 示例

以下示例演示如何探测表与索引的各个底层分叉大小,并转换为易读格式。

测量各分叉物理大小

使用 pg_size_pretty() 将字节数格式化为人类易读单位:

SELECT 
    'orders' AS relation_name,
    pg_size_pretty(pg_relation_size('orders', 'main')) AS main_fork_size,
    pg_size_pretty(pg_relation_size('orders', 'fsm'))  AS fsm_fork_size,
    pg_size_pretty(pg_relation_size('orders', 'vm'))   AS vm_fork_size,
    pg_size_pretty(pg_relation_size('orders'))         AS default_size;

输出:

 relation_name | main_fork_size | fsm_fork_size | vm_fork_size | default_size 
---------------+----------------+---------------+--------------+--------------
 orders        | 120 MB         | 256 kB        | 32 kB        | 120 MB

单独测量特定索引所占空间

pg_relation_size() 不仅支持数据表,也能精准测量特定索引文件的开销:

SELECT 
    indexrelid::regclass AS index_name,
    pg_size_pretty(pg_relation_size(indexrelid)) AS index_size
FROM pg_index
WHERE indrelid = 'orders'::regclass;

输出:

     index_name     | index_size 
--------------------+------------
 orders_pkey        | 22 MB
 idx_orders_user_id | 18 MB
 idx_orders_created | 15 MB

通过这一查询,DBA 可以直观确认哪些辅助索引体积过大,评估是否有冗余索引需要精简。

结论

  • pg_relation_size('table') 仅计算主表主分叉本身,不包含该表的 TOAST 表以及辅助索引。
  • 当你需要衡量一张表包含 TOAST 变长大字段在内的整体数据大小时,应使用 pg_table_size();若需度量整张表及其所有关联索引的总物理空间,应使用 pg_total_relation_size()。
  • 理解这三者的层级包含关系是每一位 PostgreSQL 资深开发人员与 DBA 的核心功底。