我有一个postgresql数据库和一个包含近十亿行的表。 当我尝试添加一个默认值的新列时:
ALTER TABLE big_table
ADD COLUMN some_flag integer NOT NULL DEFAULT 0;
交易持续30多分钟......数据库日志开始发出警告。
如何优化查询?
答案 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'”的列将会很快。