PostgreSQL 教程: 检查数据库膨胀

五月 8, 2026

摘要:在本教程中,您将学习如何在 PostgreSQL 中检查数据库膨胀。

目录

介绍

您可以使用 PostgreSQL 多版本并发控制(MVCC)来帮助保持数据完整性。PostgreSQL 的 MVCC 工作原理是保存一个更新或删除的行(也称为元组)的内部副本,直到事务被提交或回滚。保存的内部副本对用户不可见。但是,当 VACUUM 或 AUTOVACUUM 程序未定期清理这些不可见的副本时,可能会出现表膨胀。如果不加以控制,表膨胀可能会导致存储成本增加,并降低数据库系统处理速度。

查询表膨胀

PostgreSQL 可能会存在大量死元组累积而未触发自动清理。然而,即使死行数量过多,最终VACUUM也可能会清除它们。但这会在表中留下过多的空闲空间(“膨胀”)。PostgreSQL 不会跟踪表中的空闲空间,这使得监控这些空闲空间变得困难。虽然有一些监控查询会尝试猜测出表中的空闲空间,但它们经常会出错。监控膨胀的唯一可靠方法是使用 pgstattuple 扩展:

SELECT t.table_name,
       s.free_percent,
       s.free_space
FROM (SELECT c.oid::regclass AS table_name,
             CASE WHEN s.size > 163840
                  THEN FALSE
                  ELSE TRUE
             END AS tiny
      FROM pg_class AS c
         CROSS JOIN LATERAL pg_relation_size(c.oid) AS s(size)
      WHERE c.relkind IN ('r','t')
      /* prevent subquery flattening */
      OFFSET 0) AS t
   CROSS JOIN LATERAL pgstattuple(t.table_name) AS s
WHERE NOT t.tiny
ORDER BY free_percent DESC
LIMIT 20;

该查询列出空闲空间百分比最高的 20 个表。它会忽略小表(少于 20 个数据块),因为它们会影响统计结果。

该查询将对所有表执行顺序扫描,因此您应该仅在空闲时间偶尔去运行它。您可以考虑使用pgstattuple_approx()函数代替pgstattuple(),因为pgstattuple_approx()函数只会扫描表的一部分以获得近似结果。

膨胀量与数据库的大小有关。如果您运行的数据库较小,总数据量只有 20 GB,那么这个数据量可能会很明显,并且清理一下也很有用,但您也可以推迟一段时间。如果您存储了数百 GB 的数据,其中有 100 GB 或更多的膨胀,在这种情况下占了数据库的很大一部分,那么它真的值得进行清理。

了解更多

PostgreSQL 监控