在添加NOT NULL
带有DEFAULT
值的列时-PostgreSQL是否优化了此操作?
如果表有n行,那么未优化的alter-table-add-column将产生默认值的n次写入-显然,这很痛苦。通过优化,数据库将立即创建新列,仅存储默认值的一个副本,当在合适的索引数据结构中找不到该列的非默认值时将返回该默认值。
例如,Oracle 11g进行了这样的优化。
在添加NOT NULL
带有DEFAULT
值的列时-PostgreSQL是否优化了此操作?
如果表有n行,那么未优化的alter-table-add-column将产生默认值的n次写入-显然,这很痛苦。通过优化,数据库将立即创建新列,仅存储默认值的一个副本,当在合适的索引数据结构中找不到该列的非默认值时将返回该默认值。
例如,Oracle 11g进行了这样的优化。
Answers:
PostgreSQL中没有这种机制。
但是,您仍然可以避免这种表更改的过度影响。
以下语句在语句/事务期间获得对表的访问排他锁:
ALTER TABLE your_table
ADD COLUMN new_column integer NOT NULL DEFAULT 0;
该语句更改目录,然后重写整个表,以便新列在所有行中都包含默认值。如果表有很多行并且被足够频繁地访问,这将导致一些暂时的问题。
为了避免这种情况,请尝试将排他锁保持得尽可能短:
ALTER TABLE your_table
ADD COLUMN new_column integer;
ALTER TABLE your_table
ALTER COLUMN new_column SET DEFAULT 0;
因为这基本上只是对目录的更改(实际上是两次)(没有发生数据更改),所以它将很快完成。然后,根据您的需要和表的使用情况,您可以一步或批量将新列更新为默认列,完成后将列设置为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/
此功能是新增功能,并已发布在版本11中。
ALTER TABLE your_table
ADD COLUMN new_column integer NOT NULL DEFAULT 0;
上面就是这样的命令,它将受到此优化的影响;但是,应该说,NOT NULL
是不是必需的。现在对添加有非空默认值的任何新列进行优化。您可以在此commitfest中找到该条目。您还应该检查一下有关它的出色文章,“ Postgres 11中的缺失链接:使用默认值快速创建列”。
如果您想避免桌子上的排他性表锁,请遵循Craig Ringer的建议,
DEFAULT
ALTER
它添加DEFAULT
之后,所以它适用于新插入的行UPDATE
s 在现有行上填充新列NOT NULL
约束