我们有一个 PostgreSQL 数据库,它的大小最近显着增长,在过去的几个月里从大约 340GB 增加到 571GB,我们没有跟踪在那段时间用户行为的任何重大变化。我们的主要 DBA 提出了一些建议,他的主要建议是导出整个数据库,然后重新导入它,根据他在从我们的主数据库克隆的第二台服务器上的测试,这需要大约 3 小时的停机时间,并获得大小降到只有 300GB。
我关心的两个主要领域是找出这种显着增长的来源(使用 du -h 我至少可以看到它在 /data 目录中,表空间或 pg_wal 没有显着增长),并了解如何导入和导出该数据库可以为我们带来将近 300GB 的空间恢复,而不会实际丢失任何生产数据。
我要做的第一件事是进入数据目录并运行
这将显示在哪些子目录中使用了大量磁盘空间。您可以通过向下深入并重复该命令来向下钻取。
通常,磁盘使用量的增加来自以下两个原因之一:
pg_wal
无法删除WAL in 。这可能是因为归档程序有问题(查看pg_stat_archiver
)或者您有一个过时的复制槽(查看pg_replication_slots
)。一些表或索引膨胀。
如果您使用 /restore 创建了数据库的副本
pg_dump
,那么您已经完成了解决方案的一半。在两个数据库上运行类似的东西:比较双方的输出,观察原始数据库中的表和索引是否大得多。
通过检查可能的原因来修复膨胀。
VACUUM (FULL)
完成此操作后,请使用(注意,这需要停机时间)摆脱bload 。最终,我们使用以下方法来确定问题:
我们在测试数据库服务器上进行了导出和导入,因此我们有一个完整大小的数据库副本,以及一个较小的导入后大小的数据库副本。
然后我们运行以下查询来识别最大的表:
SELECT schema_name as table_schema, relname as table_name, pg_size_pretty(pg_relation_size(relid)) as data_size FROM pg_catalog.pg_stat_all_tables ORDER BY pg_relation_size(relid) DESC;
这清楚地表明,在主系统上,表 pg_catalog.pg_largeobject 刚刚超过 200GB,而在导出和导入之后的测试系统上,它是 0 字节。
我们现在正在制定一项计划,以更好地管理 pg_largeobject 的增长。