18

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

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

事务持续了 30+ 分钟 .. 并且数据库日志开始发出警告。

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

4

3 回答 3

9

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

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

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

另一种选择是fsync在运行命令时关闭...只要记住重新打开它。

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

于 2012-12-08T15:50:12.003 回答
7

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

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

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

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'”的列会很快。

于 2018-04-25T17:15:40.090 回答
5

我会考虑在没有默认值的情况下创建列,并通过间歇性提交手动更新行以应用默认值。

于 2012-12-08T11:51:00.927 回答