我正在尝试编写一个 munin 插件来绘制数据库大小。除了使用pg_database_size
我还想绘制其组件。
到目前为止,我想出了以下几点:
SELECT
SUM(pg_relation_size(oid, 'main')) AS main_size,
SUM(pg_relation_size(oid, 'vm')) AS vm_size,
SUM(pg_relation_size(oid, 'fsm')) AS fsm_size,
SUM(
CASE reltoastrelid
WHEN 0 THEN 0
ELSE pg_total_relation_size(reltoastrelid)
END
) AS toast_size,
SUM(pg_indexes_size(oid)) AS indexes_size
FROM pg_class
WHERE reltype != 0 -- 0=indices, covered by pg_indexes_size
但是,总结这 5 个值会给我一些与pg_database_size
. 对于较大的数据库,差异似乎不太显着。
较大数据库上的示例:
┌──────────┬────────┬─────────┬─────────┬──────────┬───────────────┬──────────────────┬─────────┐
│ main │ vm │ fsm │ toast │ indexes │ sum_of_values │ pg_database_size │ diff │
├──────────┼────────┼─────────┼─────────┼──────────┼───────────────┼──────────────────┼─────────┤
│ 72441856 │ 753664 │ 2392064 │ 4677632 │ 41377792 │ 116 MB │ 111 MB │ 5222 kB │
└──────────┴────────┴─────────┴─────────┴──────────┴───────────────┴──────────────────┴─────────┘
(1 row)
较小数据库的示例:
┌─────────┬────────┬─────────┬────────┬─────────┬───────────────┬──────────────────┬─────────┐
│ main │ vm │ fsm │ toast │ indexes │ sum_of_values │ pg_database_size │ diff │
├─────────┼────────┼─────────┼────────┼─────────┼───────────────┼──────────────────┼─────────┤
│ 2809856 │ 385024 │ 1351680 │ 557056 │ 2924544 │ 7840 kB │ 6642 kB │ 1198 kB │
└─────────┴────────┴─────────┴────────┴─────────┴───────────────┴──────────────────┴─────────┘
(1 row)
我错过了什么?
也许相关,也许不相关:看到索引大小我很震惊。他们是巨大的。我的查询中有问题吗?
这是我用来检查不同值的脚本:
SELECT
SUM(pg_relation_size(oid, 'main')) AS main,
SUM(pg_relation_size(oid, 'vm')) AS vm,
SUM(pg_relation_size(oid, 'fsm')) AS fsm,
SUM(
CASE reltoastrelid
WHEN 0 THEN 0
ELSE pg_total_relation_size(reltoastrelid)
END
) AS toast,
SUM(pg_indexes_size(oid)) AS indexes,
pg_size_pretty(
SUM(pg_relation_size(oid, 'main'))::bigint +
SUM(pg_relation_size(oid, 'vm'))::bigint +
SUM(pg_relation_size(oid, 'fsm'))::bigint +
SUM(pg_indexes_size(oid))::bigint +
SUM(
CASE reltoastrelid
WHEN 0 THEN 0
ELSE pg_total_relation_size(reltoastrelid)
END
)::bigint
) AS sum_of_values,
pg_size_pretty(pg_database_size(current_database())) AS pg_database_size,
pg_size_pretty(
SUM(pg_relation_size(oid, 'main'))::bigint +
SUM(pg_relation_size(oid, 'vm'))::bigint +
SUM(pg_relation_size(oid, 'fsm'))::bigint +
SUM(pg_indexes_size(oid))::bigint +
SUM(
CASE reltoastrelid
WHEN 0 THEN 0
ELSE pg_total_relation_size(reltoastrelid)
END
)::bigint - pg_database_size(current_database())::bigint
) AS diff
FROM pg_class
WHERE reltype != 0;
你数了两次吐司桌。一次在他们的所有者下, as
pg_total_relation_size(reltoastrelid)
,然后在他们自己的 pg_class 条目下。您应该使用 relkind 而不是 reltype 来过滤您想要的内容。此外,在这种程度上尝试对您的 RDBMS 进行微观管理很少有回报。
pg_database_size()
本质上是在文件系统中查询$PGDATA/base/oid-of-database
(每个数据库的数据目录)的大小,加上在非默认表空间中添加的每个此类目录的大小CREATE TABLESPACE
。如果这些目录中有不属于任何关系的文件,它们也会被计算在内。查看一个随机数据库,我可以看到
pg_internal.init
,PG_VERSION
,pg_filenode.map
在这种情况下。它们加起来等于目录大小,不会计入任何控制查询。杂散数据文件也可能存在。有关具体示例,请参阅如何回收部分构建并因断电而终止的索引占用的空间。
pg_class
根据定义,它们也无法通过查询来找到,它们被计入磁盘上的 db 大小。关于查询,仅出于获取对象大小总和的目的,我建议使用更简单的版本:
请注意,共享关系已从此查询 (
not relisshared
) 中删除。共享对象在所有数据库中都是可见的,并且不属于任何数据库的目录,它们位于$PGDATA/global
. 预计会很大的共享表之一是pg_shdepend
. 在您的原始查询中忽略这一点会使其高估(除了@jjanes 关于 toast 表的评论)。