PostgreSQL 是否优化添加具有非 NULL DEFAULT 的列?

max*_*zig 12 postgresql optimization alter-table ddl

添加NOT NULL带有DEFAULT值的列时- PostgreSQL 是否优化此操作?

如果表有 n 行,未优化的 alter-table-add-column 将产生 n 次写入默认值 - 显然,这可能非常痛苦。通过优化,数据库将立即创建新列,仅存储默认值的一个副本,当在合适的索引数据结构中找不到该列的非默认值时,该副本将返回。

例如Oracle 11g 就有这样的优化

dez*_*zso 17

PostgreSQL 中没有这样的机制。

但是,您仍然可以避免这种表更改的过度影响。

以下语句在语句/事务期间获取对表的访问排他锁

ALTER TABLE your_table
    ADD COLUMN new_column integer NOT NULL DEFAULT 0;
Run Code Online (Sandbox Code Playgroud)

此语句更改目录,然后重写整个表,以便新列在所有行中都包含默认值。如果表有很多行并且访问频率足够高,这会导致一些临时问题。

为避免这种情况,请尝试尽可能短地保持排他锁:

ALTER TABLE your_table
    ADD COLUMN new_column integer;
ALTER TABLE your_table
    ALTER COLUMN new_column SET DEFAULT 0;
Run Code Online (Sandbox Code Playgroud)

由于这基本上只是对目录的一个(实际上是两个)更改(没有发生数据更改),因此它会很快完成。然后根据您的需要和表的使用情况,可以一步或批量更新新列为默认值,完成后将该列设置为NOT NULL

关于愿望成真的更新: PostgreSQL 11 将具有此功能。有关更多信息,请参阅https://www.depesz.com/2018/04/04/waiting-for-postgresql-11-fast-alter-table-add-column-with-a-non-null-default/


Eva*_*oll 9

是的,使用 PostgreSQL 11

此功能是新功能,已在版本 11 中推出。

ALTER TABLE your_table
    ADD COLUMN new_column integer NOT NULL DEFAULT 0;
Run Code Online (Sandbox Code Playgroud)

上面是一个这样的命令,会受到这个优化的影响;但是,应该说,NOT NULL不是必需的。任何添加了非空默认值的新列现在都得到了优化。您可以在此 commitfest 中找到该条目您还应该查看有关它的这篇很棒的文章,“Postgres 11 中的缺失链接:使用默认值快速创建列”

Pre-PostgreSQL 11 解决方法

如果您想避免桌子上的独占桌子锁,请遵循 Craig Ringer 的建议,

  • 添加一列不带 DEFAULT
  • ALTER它添加DEFAULT之后的所以它适用于新插入的行
  • 然后填充通过逐步分批对现有行的新列UPDATE小号
  • 当所有行都具有您添加NOT NULL约束的值时