我们有一个大小刚刚超过 200 GB 的数据库,包含大约 4.3 亿行、一个主键和一个空间索引。每隔几周我们就会收到一次更新,其中涉及大约 300 万行,删除一些旧功能并更新新功能。这是离线完成的。我们还有一个历史表,它存储每次更新的累积删除。该表目前大约 20 GB,40 有百万行。本质上,我们首先将更改表中标记为删除的任何内容插入到历史表中,然后从主表中删除所有内容,即删除或新建,然后将所有更改的记录(所有离线,要清楚)。
如果我在单个过程/函数中运行它,似乎会触发表重写,因为我在几个小时后回来发现它由于用完可用的磁盘空间(大约 100 GB)而失败。如果我在 psql 控制台中逐行运行它,则没有这样的问题。由于没有 DDL 语句,并且更改的行总数远小于数据库总大小,我对可能导致如此多的临时磁盘使用量的原因感到困惑,因为将整个更改记录为一个所需的总空间交易似乎要少得多。
是否有一些经验法则或一个简单的诊断查询,我可以运行它来查看发生了什么?
我想说不同之处在于您的 PL/PgSQL 过程在单个事务中运行。
如果您在 中逐行运行
psql
,除非您明确地BEGIN
和,否则您COMMIT
将在单个事务中运行。这可能会慢很多,但这也意味着 autoVACUUM
可以释放并重用已删除的行,因此后续UPDATE
s 可以将新的行版本写入那些释放的空间。如果您在单个事务中,系统必须保留旧的行版本,因为它需要它们以防您
ROLLBACK
进行事务或遇到错误。因此,除非您愿意使用诸如
dblink
. 您需要将您的工作批量处理为一系列较小的事务,并且由于 PostgreSQL 还不支持从 PL/PgSQL 函数内部进行自主提交,这意味着 dblink 或外部客户端。