我的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;

我认为这些说法没有区别,但是:

  1. 我在文件中找不到任何证据.文档显示,为新列提供DEFAULT值会使PostgreSQL重写所有元组,但我认为在这种情况下不是这样,因为默认值是NULL.
  2. 我在这个表的副本上运行了一些测试,第一个语句(没有DEFAULT NULL个)比第二个语句花费的时间多一点.我不明白为什么.

我的问题是:

  1. PostgreSQL会对这两条语句使用相同的锁类型(ACCESS EXCLUSIVE)吗?
  2. 如果我使用DEFAULT NULL,PostgreSQL会重写所有元组, for each 元组添加NULL个值吗?
  3. 这两种说法有什么不同吗?

推荐答案

https://www.postgresql.org/docs/current/static/sql-altertable.html

  1. 是-相同的ACCESS EXCLUSIVE,默认值为NULL或未提及默认值时没有例外(我认为统计数据、"选项"、约束、集群要求不那么严格,但不需要添加列)

请注意,每个子窗体所需的锁定级别可能不同.一

  1. 否-它宁愿在 Select 时将NULL附加到结果

使用"添加列"添加列时,表中的所有现有行

  1. 没有,没有区别.这两种情况下的元数据变化(我认为这是一种用不同语义表示的情况)

编辑-演示:

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

Postgresql相关问答推荐

在Haskell中定义新类型与持久化类型的惯用方法

时间戳的postgreSQL-to_char如果为零,则不显示微秒

气流数据库如何定期管理?

如何使用 PostgreSQL 数据库中的函数和存储过程从动态表中获取所有数据?参数传入的表名

我在try 访问我的数据库表时在 postgresql 中收到 aclcheck_error 错误

是否可以短时间运行 VACUUM FULL 并获得一些好处?

PostgreSQL - 继承表的常见自动增量

有对(type_id,element_id),如(1,1),(1,2),..(5,3).如果我需要获取没有 element_id 1 的类型 ID,如何从结果中排除 type_id?

psql中set、\set和\pset的区别

在 CentOS 上安装 psycopg2 时遇到问题

Select 日期最高的行

如何将 DELETE 的返回值插入到 postgresql 中的 INSERT 中?

'active' 标志与否?

使用 postgres regexp_replace 将字符串列表替换为始终相同的字符串

如何在 psql 控制台中打印当前工作目录?

具有 DEFAULT NULL 的 MySQL 列 ?

如何为 Postgres psql 设置时区?

如何在 redshift 中对字段进行 GROUP BY 和 CONCATENATE

使用 Postgresql 在过滤器中制作 Sqlalchemy 使用日期

Capistrano 与 PostgreSQL,错误:database is being accessed by other users