在没有锁定问题的情况下在大表中创建一个NOT NULL列?

时间:2017-02-06 14:51:08

标签: postgresql

我想将列更改为NOT NULL:

ALTER TABLE "foos" ALTER "bar_id" SET NOT NULL

" foos"表有近1 000 000条记录。它的写入量相当低,但却不断。有很多阅读。

根据我的经验,将大表中的列更改为NOT NULL会导致应用程序停机,这可能是因为它会导致(b)锁定。

但是,我还没有找到证实这一点的好解释。

如果确实如此,我该怎么办才能避免它?

编辑:The docs(通过this comment)说:

  

添加带有DEFAULT子句的列或更改现有列的类型将需要重写整个表及其索引。

我不确定更改NULL是否计为&#34;更改现有列的类型&#34;,但我相信我上次看到此问题时确实在列上有索引。< / p>

也许删除索引,使列NOT NULL,然后再添加索引会改善一些事情吗?

1 个答案:

答案 0 :(得分:4)

我认为你可以使用检查约束而不是set not null来做到这一点。

ALTER TABLE foos 
     add constraint id_not_null check (bar_id is not null) not valid;

这仍然需要桌面上的ACCESS EXCLUSIVE锁,但它非常快,因为Postgres没有验证约束(因此它不必扫描整个表)。这将确保新行(或更改的行)不能将空值放入该列

然后(在提交alter table之后!)你可以这样做:

alter table foos validate constraint id_not_null;

哪个需要ACCESS EXCLUSIVE锁,但仍然允许访问该表。