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

时间:2012-12-08 11:35:30

标签: postgresql

我有一个postgresql数据库和一个包含近十亿行的表。 当我尝试添加一个默认值的新列时:

ALTER TABLE big_table
ADD COLUMN some_flag integer NOT NULL DEFAULT 0;

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

如何优化查询?

3 个答案:

答案 0 :(得分:8)

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

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

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

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

您也可以批量执行上述两项操作。

答案 1 :(得分:5)

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

答案 2 :(得分:3)

从PostgreSQL 11开始,此行为将发生变化。

Waiting for PostgreSQL 11 – Fast ALTER TABLE ADD COLUMN with a non-NULL default

  

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

alter table x add column z text;
     

几乎是瞬间完成的。获取锁定表,将有关新列的信息添加到系统目录中,并完成。

     

但是当你尝试的时候:

alter table x add column z text default 'some value';
     然后花了很长时间。它的长短取决于桌子的大小。

     

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

     

"如果要将列设置为NOT NULL,会发生什么?在这种情况下,我们是否会回到慢速版本,还是处理这个版本?"

     

not null不会改变任何内容。它是新行的约束。因此,添加“not null default'xxx'”的列将会很快。