比如查看public下的user表
\set tbl_name 'user'
SELECT l.metric, l.nr AS bytes
, CASE WHEN is_size THEN pg_size_pretty(nr) END AS bytes_pretty
, CASE WHEN is_size THEN nr / NULLIF(x.ct, 0) END AS bytes_per_row
FROM (
SELECT min(tableoid) AS :tbl_name -- = 'public.:tbl_name'::regclass::oid
, count(*) AS ct
, sum(length(t::text)) AS txt_len -- length in characters
FROM public.:tbl_name t -- provide table name *once*
) x
CROSS JOIN LATERAL (
VALUES
(true , 'core_relation_size' , pg_relation_size(:tbl_name))
, (true , 'visibility_map' , pg_relation_size(:tbl_name, 'vm'))
, (true , 'free_space_map' , pg_relation_size(:tbl_name, 'fsm'))
, (true , 'table_size_incl_toast' , pg_table_size(:tbl_name))
, (true , 'indexes_size' , pg_indexes_size(:tbl_name))
, (true , 'total_size_incl_toast_and_indexes', pg_total_relation_size(:tbl_name))
, (true , 'live_rows_in_text_representation' , txt_len)
, (false, '------------------------------' , NULL)
, (false, 'row_count' , ct)
, (false, 'live_tuples' , pg_stat_get_live_tuples(:tbl_name))
, (false, 'dead_tuples' , pg_stat_get_dead_tuples(:tbl_name))
) l(is_size, metric, nr);
metric | bytes | bytes_pretty | bytes_per_row
-----------------------------------+-------+--------------+--------------------
core_relation_size | 8192 | 8192 bytes | 2730.6666666666665
visibility_map | 0 | 0 bytes | 0
free_space_map | 0 | 0 bytes | 0
table_size_incl_toast | 16384 | 16 kB | 5461.333333333333
indexes_size | 16384 | 16 kB | 5461.333333333333
total_size_incl_toast_and_indexes | 32768 | 32 kB | 10922.666666666666
live_rows_in_text_representation | 171 | 171 bytes | 57
------------------------------ | | |
row_count | 3 | |
live_tuples | 3 | |
dead_tuples | 1 | |
core_relation_size: 这反映了表的基本存储大小,不包括 TOAST 数据、索引或任何其他附属结构。这个值通常是精确的,因为它直接由系统函数 pg_relation_size 获取。
visibility_map: 显示的是可见性图的大小。如果为0,可能是因为表太小,没有足够的数据来生成可见性图,或者表的数据都在一个页面内,所以全都是可见的。
free_space_map: 这显示了用于跟踪表中空闲空间的空间大小。如果为0,这通常意味着表当前没有足够的数据分散到多个页面,因此没有必要维护一个空间映射。
table_size_incl_toast: 包含 TOAST 数据的表的总大小,这个度量是精确的,并且包括了表本身以及任何大型字段的存储。
indexes_size: 所有索引的总大小。这个值也是精确的,由系统函数 pg_indexes_size 计算得出。
total_size_incl_toast_and_indexes: 表的总大小,包括 TOAST 和所有索引。这个值是通过系统函数 pg_total_relation_size 得出的,是精确的。
live_rows_in_text_representation: 这个度量指标显示的是如果将表中的活跃行转换为文本形式时的总字符数。这个值取决于行的内容,可能因数据类型和存储效率而有所不同。
row_count: 表中的总行数。这是一个精确的值,反映了表中目前的行数。
live_tuples: 活跃元组的数量。这个值与 row_count 相同,表示表中活跃的数据行。
dead_tuples: 死亡元组的数量,表示已经被更新或删除的行,但尚未被清除(如通过 VACUUM 操作)。这个数字的准确性取决于最后一次 VACUUM 操作后表的活动量。
无论是通过减少死亡元组、优化索引还是合理管理TOAST数据,理解这些存储指标都可以为你的数据库优化提供有力支持。如果你想让数据库在性能和存储占用之间达到平衡,掌握这些关键指标并加以优化无疑是重要的一步。
「欢迎关注我们的公众号,获取更多技术分享与经验交流。」




