将具有DEFAULT值的COLUMN添加到一个巨大的表中

d.r*_*aev 10 postgresql

我有一个postgresql数据库和一个有几十亿行的表.当我尝试添加具有默认值的新列时:

ALTER TABLE big_table
ADD COLUMN some_flag integer NOT NULL DEFAULT 0;
Run Code Online (Sandbox Code Playgroud)

交易持续30多分钟......数据库日志开始发出警告.

有什么方法可以优化查询?

Ada*_*ent 9

除了分批进行(仍需要一段时间):

您可以将表转储为COPY语句并编写脚本以编辑COPY语句的内容以插入另一列(COPY可以是CSV IIRC).

然后你只需重新加载你改变的COPY转储,理论上它应该比ALTER因为COPY不会记录事务更快.

另一个选项是fsync在运行命令时关闭...只需记住将其重新打开即可.

您也可以批量执行上述两个操作.


Luk*_*zda 6

从 PostgreSQL 11 开始,这种行为将会改变。

等待 PostgreSQL 11 – 具有非 NULL 默认值的快速 ALTER TABLE ADD COLUMN

所以,在最长的时间里,当你这样做时:

alter table x add column z text;
Run Code Online (Sandbox Code Playgroud)

它几乎是瞬间完成的。锁定表,将有关新列的信息添加到系统目录,就完成了。

但是当你尝试:

alter table x add column z text default 'some value';
Run Code Online (Sandbox Code Playgroud)

然后花了很长时间。多长时间取决于桌子的大小。

这是因为 postgresql 实际上是重写整个表,将列添加到每一行,并用默认值填充它。

“如果你也想将列设置为 NOT NULL 会发生什么?在这种情况下我们是回到慢速版本还是也能处理这个问题?”

not null 不会改变任何东西。它是新行的约束。所以添加一个带有“not null default 'xxx'”的列会很快。


Dav*_*dge 5

我会考虑创建没有默认值的列,并使用间歇提交手动更新批量行以应用默认值.