有三种方法可以得到这种计数,每种方法都有自己的权衡。
如果您想要真实的计数,则必须像针对每个表使用的那样执行 SELECT 语句。这是因为 PostgreSQL 将行可见性信息保存在行本身中,而不是其他任何地方,因此任何准确的计数只能与某些事务相关。您将获得该事务在执行时所看到的内容的计数。您可以自动执行此操作以针对数据库中的每个表运行,但您可能不需要那么高的准确性或希望等待那么长时间。
WITH tbl AS
(SELECT table_schema,
TABLE_NAME
FROM information_schema.tables
WHERE TABLE_NAME not like 'pg_%'
AND table_schema in ('public'))
SELECT table_schema,
TABLE_NAME,
(xpath('/row/c/text()', query_to_xml(format('select count(*) as c from %I.%I', table_schema, TABLE_NAME), FALSE, TRUE, '')))[1]::text::int AS rows_n
FROM tbl
ORDER BY rows_n DESC;
第二种方法指出,统计收集器随时跟踪大致有多少行是“活动的”(未删除或被以后的更新废弃)。在繁重的活动下,该值可能会略有偏差,但通常是一个不错的估计:
SELECT schemaname,relname,n_live_tup
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC;
这还可以显示有多少行已死亡,这本身就是一个值得监视的有趣数字。
第三种方法是注意系统 ANALYZE 命令(从 PostgreSQL 8.3 开始由 autovacuum 进程定期执行以更新表统计信息)也会计算行估计。你可以像这样抓住那个:
SELECT
nspname AS schemaname,relname,reltuples
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE
nspname NOT IN ('pg_catalog', 'information_schema') AND
relkind='r'
ORDER BY reltuples DESC;
很难说使用这些查询中哪一个更好。通常我会根据我是否还想在 pg_class 内部或 pg_stat_user_tables 内部使用更有用的信息来做出决定。出于基本的计数目的,只是为了了解物体的总体大小,两者都应该足够准确。