我在 PostgresSQL 上有一个包含数百万行的表。该表有列 a 和 b。我已经在 a 和 b 上有一个唯一索引:
CONSTRAINT a_b UNIQUE (a, b)
我想在 a 和 b 列上添加一个复合主键。
如果我做一个
ALTER TABLE table_name ADD PRIMARY KEY (a, b);
我在 PostgresSQL 上有一个包含数百万行的表。该表有列 a 和 b。我已经在 a 和 b 上有一个唯一索引:
CONSTRAINT a_b UNIQUE (a, b)
我想在 a 和 b 列上添加一个复合主键。
如果我做一个
ALTER TABLE table_name ADD PRIMARY KEY (a, b);
虽然
CREATE INDEX
只阻止并发写入并仍然允许读取,但您需要ALTER TABLE
添加PRIMARY KEY
约束,这会ACCESS EXCLUSIVE
锁定表,同时阻止读取。所以,是的,如果表是必不可少的,我会称之为“停机时间”。然而,有减轻痛苦的选择。
首先,两个索引列都必须是
NOT NULL
. 虽然UNIQUE
约束/索引允许null
值,但 PK 不允许。如果不是这种情况,请先修复它。否则,后者ALTER TABLE
会为您完成,从而延长停机时间。手册:所以,首先(在固定任何
null
值之后):然后,问题是:唯一索引或约束?可以在非常快速的“仅元数据”操作中重新调整索引的用途。不幸的是,对于约束来说,这是不可能的。有人可能会认为它应该是:它仍然是相同的索引。但它只是没有实施。任何人都会打扰的用例太罕见了。您可能可以破解系统目录。但我不会去那里。一个错误的举动,你可以破坏整个数据库。以前也有类似的需求,我也没去:
因此,如果它是一个约束,则首先构建第二个其他方面相同的唯一索引。使用一个临时名称,它稍后会被扔出窗外。
CREATE INDEX CONCURRENTLY
自 Postgres 8.2(现在几乎永远)以来,我们对任务具有非阻塞性。最后,删除约束,并在现有或新索引上添加 PK 构建:
这需要所说的
ACCESS EXCLUSIVE
锁。但是所有的艰苦工作都已经完成,所以这应该是几毫秒的事情——一旦并发事务让它获得锁。小提琴