我的PostgreSQL 9.6数据库中有一个表,有300万行。该表已经有一个空位图(它还有另外两个DEFAULT NULL
字段)。我想在这个表中添加一个新的布尔可空列。我坚持这两个陈述之间的区别:
ALTER TABLE my_table ADD COLUMN my_column BOOLEAN;
ALTER TABLE my_table ADD COLUMN my_column BOOLEAN DEFAULT NULL;
我认为这些陈述没有区别,但是:
DEFAULT
值会使PostgreSQL重写所有元组,但我不认为这种情况是正确的,因为默认值为NULL
。DEFAULT NULL
)花费的时间比第二个多一点。我不明白为什么。我的问题是:
ACCESS EXCLUSIVE
)吗?NULL
,PostgreSQL是否会重写所有元组以向其中添加DEFAULT NULL
值?答案 0 :(得分:14)
第2点 Vao Tsun 的回应存在问题。
如果使用ALTER TABLE my_table ADD COLUMN my_column BOOLEAN;
,它将不会重写所有元组,只会改变元数据。
但是如果你使用ALTER TABLE my_table ADD COLUMN my_column BOOLEAN DEFAULT NULL
,它将重写所有元组,并且它将在长桌上持续使用。
文档本身告诉了这一点。
使用ADD COLUMN添加列时,表中的所有现有行都使用列的默认值进行初始化(如果未指定DEFAULT子句,则为NULL)。 如果没有DEFAULT子句,这只是元数据更改,不需要立即更新表的数据;相反,在读数时提供了添加的NULL值。
这告诉我们如果有一个DEFAULT子句,即使它是NULL,它也会重写所有元组。
这是由于更新子句的性能问题。如果你需要对一个没有重写的元组进行更新,它需要将元组移动到另一个磁盘空间,耗费更多时间。
我在Postgresql 9.6 上测试了这个,当我不得不在一个有3亿多元组的表上添加一列时。没有DEFAULT NULL
它持续了11毫秒,而DEFAULT NULL
它持续了超过30分钟。
答案 1 :(得分:3)
https://www.postgresql.org/docs/current/static/sql-altertable.html
ACCESS EXCLUSIVE
,没有DEFAULT NULL的例外或没有提到DEFAULT(统计信息,“选项”,约束,群集需要不那么严格我想,但不是添加列)请注意,每个子表单所需的锁定级别可能不同。一个 除非明确说明,否则将保持ACCESS EXCLUSIVE锁定。当多个 列出了子命令,锁定将是最严格的 任何子命令都需要。
使用ADD COLUMN添加列时,表中的所有现有行 使用列的默认值初始化(如果没有DEFAULT,则为NULL) 指定的子句)。如果没有DEFAULT子句,这只是一个 元数据更改,不需要立即更新 表的数据;相反,在读数时提供了添加的NULL值。
编辑 - 演示:
db=# create table so(i int);
CREATE TABLE
Time: 9.498 ms
db=# insert into so select generate_series(1,10*1000*1000);
INSERT 0 10000000
Time: 13899.190 ms
db=# alter table so add column nd BOOLEAN;
ALTER TABLE
Time: 1025.178 ms
db=# alter table so add column dn BOOLEAN default null;
ALTER TABLE
Time: 13.849 ms
db=# alter table so add column dnn BOOLEAN default true;
ALTER TABLE
Time: 14988.450 ms
db=# select version();
version
----------------------------------------------------------------------------------------------------------------
PostgreSQL 9.6.1 on x86_64-apple-darwin15.6.0, compiled by Apple LLVM version 8.0.0 (clang-800.0.42.1), 64-bit
(1 row)
最后为了避免猜测它是特定于数据类型的:
db=# alter table so add column t text;
ALTER TABLE
Time: 25.831 ms
db=# alter table so add column tn text default null;
ALTER TABLE
Time: 13.798 ms
db=# alter table so add column tnn text default 'null';
ALTER TABLE
Time: 15440.318 ms