3

有没有办法在不将磁盘大小加倍的情况下向 Postgresql 表添加非空类型列?例如,如果我有一个定义了一些列的表,并且我想添加一个列,我会执行以下操作:

alter table my_table add new_column int  
update table my_table set new_column = 0 
alter table my_table alter column new_column set not null

由于 Postgresql 的工作方式,这实际上使为表分配的空间增加了一倍。更新正在创建新的元组,这些元组将在此事务完成并且真空完成其工作后被标记为重用。如果表的大小很大(即几百万行)但增长非常缓慢或大小几乎恒定,则这些行将永远不会被重用,并且只有“真空完全”或完全数据库备份和恢复会回收磁盘上的空间。有没有办法自动添加具有某些默认值但没有这种行为的列?例如,如果有一种方法可以锁定表并进行更新,那么在这种情况下就不需要 MVCC。

4

2 回答 2

4

分步骤进行:

  1. 更改表添加新列
  2. 更改表为列添加默认值
  3. 更新,但不是带有 1 个更新语句的整个表,而是像 10000 个单独的更新一样发出它,每个更新都在自己的事务中
  4. 每几百次更新运行一次vacuum,或者更好 - autovacuum
  5. 更改表集不为空
于 2010-01-18T16:32:46.237 回答
0

如果表的大小很大(即几百万行)但增长非常缓慢或大小几乎恒定,则这些行将永远不会被重用,并且只有“真空完全”或完全数据库备份和恢复会回收磁盘上的空间。

这似乎很可疑。我想知道您的可用空间图是否不够大——当这种情况发生时,postgres 开始丢失对已删除行的跟踪,并且无法回收它们,除非真空已满。如果您正在运行 Postgres <= 8.3,您是否检查过以确保您的 max_fsm_pages 足够大以跟踪已删除的行?要找出答案,尽一切可能达到这种状态,即表中有未重用的死行,然后执行“vacuum full verbose”。Postgres 会在真空结束时告诉你 fsm 问题。

max_fsm_pages 在 Postgresql 8.4 中消失了。如果您运行的是 8.4,那么没关系。

于 2010-01-19T06:23:24.037 回答