Postgresql 将具有默认值的列添加到大型表中
我有一个postgresql数据库和一个包含近十亿行的表。 当我尝试使用默认值添加新列时:Postgresql 将具有默认值的列添加到大型表中,postgresql,Postgresql,我有一个postgresql数据库和一个包含近十亿行的表。 当我尝试使用默认值添加新列时: ALTER TABLE big_table ADD COLUMN some_flag integer NOT NULL DEFAULT 0; 交易持续30分钟以上。。数据库日志开始发出警告 < >优化查询的任何方式?< /P> < P>我会考虑创建没有默认的列,并手动更新批处理的行,以间歇提交的方式应用默认的.< /P> < P>,除了按批处理(这还需要一段时间): 您可以将表转储为语句,并编写脚本来编
ALTER TABLE big_table
ADD COLUMN some_flag integer NOT NULL DEFAULT 0;
交易持续30分钟以上。。数据库日志开始发出警告
< >优化查询的任何方式?< /P> < P>我会考虑创建没有默认的列,并手动更新批处理的行,以间歇提交的方式应用默认的.< /P> < P>,除了按批处理(这还需要一段时间): 您可以将表转储为语句,并编写脚本来编辑COPY语句的内容以插入另一列(COPY可以是CSV IIRC) 然后您只需重新加载修改后的
COPY
dump,理论上它应该比ALTER
更快,因为COPY不会记录事务
另一个选项是在运行命令时关闭。。。记得把它打开
您也可以批量执行上述两项操作。从PostgreSQL 11开始,此行为将发生变化 : 所以,在最长的一段时间里,当你这样做的时候:
alter table x add column z text;
这几乎是瞬间的。锁定表,将有关新列的信息添加到系统目录中,就完成了
但当你尝试时:
alter table x add column z text default 'some value';
然后花了很长时间。多长时间取决于桌子的大小
这是因为postgresql实际上正在重写整个表,将列添加到每一行,并用默认值填充它。
“如果要将列也设置为NOTNULL,会发生什么情况?在这种情况下,我们是回到慢速版本,还是这也可以处理此问题?”
非null不会改变任何内容。这是新行的约束。因此,添加带有“NOTNULL default'xxx'”的列将非常快。
您可以在日志文件中看到哪些警告?您可以使用表的数据创建一个副本,将列添加到该副本中,然后通过重命名来交换这两个表。(您可能需要适当地处理依赖项。)@dez所以我们讨论的是10亿行繁忙表。。。复制它将如何使程序更快/better@d.raevdezso可能是对的()因为Postgres WAL的性质。我们也有同样的想法,但最终可能需要更多的时间。我需要把它放在“版本更新”事务中。。所以我在寻找一个更干净的解决方案。不管怎样,所有的行都需要被复制,以便在新列中得到一个非空值。通过在
altertable
中指定默认值,您可以一次完成所有操作,同时阻止其他访问。当其他进程访问该表时,您可以通过将该列添加为支持null的列并执行一系列小更新(可能在迭代之间进行休眠)来增量执行该操作。不要对整个表进行一次大的UPDATE
,否则会使表膨胀。为了达到最佳效果,您还需要在每个批之间进行真空处理。谢谢,我希望有更多的查询构造技巧,但似乎没有。下次我会考虑FSYNC,在十亿的末尾是十亿。这不是一个小数字:)。我很好奇数据是什么?它表示从RL文档解析的数据。当然有更好的存储概念,但改变整个结构不是一个选项,也不是对实现选择的批评。我只是好奇,因为我总是对人们在“现实世界”中如何使用东西感兴趣。