1

这里 https://stackoverflow.com/a/53016193/10894456 是为 Oracle 11g 提供的答案,我的问题是一样的:

当该表包含一百万条记录并且它处于活动状态时,在生产 oracle 数据库中添加具有默认值的非空列的最佳方法是什么。如果我们创建列,添加默认值并在单个语句中使其不为空,它会创建任何锁吗?

但是对于 PostgreSQL 呢?

4

1 回答 1

5

这个先前的答案基本上回答了您的查询。

将相关 PostgreSQL 文档与上述答案中提到的 PostgreSQL 源代码交叉引用AlterTableGetLockLevel表明,ALTER TABLE ... ADD COLUMN将始终获得ACCESS EXCLUSIVE表锁,从而在操作期间阻止任何其他事务访问表ADD COLUMN。对于任何变体,都会获得相同的排他锁ADD COLUMN;IE。添加NULL列(带有或不带有DEFAULT)或NOT NULL带有默认值都没有关系。

但是,正如上面链接的答案中提到的,添加NULL没有 no 的列DEFAULT应该非常快,因为此操作只会更新目录。

相反,添加带有DEFAULT说明符的列需要在 PostgreSQL 10 或更低版本中重写整个表。此操作可能会在您的 1M 记录表上花费相当长的时间。根据链接的答案,PostgreSQL >= 11 不需要这样的重写来添加这样的列,因此应该执行更类似于 no- DEFAULTcase。

我应该补充一点,对于 PostgreSQL 11 及更高版本,ALTER TABLE文档指出只有非易失性DEFAULT说明符才能避免表重写:

当使用 ADD COLUMN 添加列并指定非易失性 DEFAULT 时,会在执行语句时评估默认值,并将结果存储在表的元数据中。该值将用于所有现有行的列。如果未指定 DEFAULT,则使用 NULL。在这两种情况下都不需要重写表。

添加具有 volatile DEFAULT [...] 的列将需要重写整个表及其索引。[...] 表和/或索引重建可能需要大量时间来处理大型表;并且将暂时需要两倍的磁盘空间。

于 2020-04-30T05:20:27.797 回答