![](/img/trans.png)
[英]Postgresql - CHECK constraint not preventing ACCESS EXCLUSIVE lock and table scan when attaching new partition
[英]Avoid scan on attach partition with check constraint
我正在 PostgreSQL 11 中將現有表重新創建為分區表。
經過一些研究,我正在使用以下過程來處理它,因此可以在桌子上仍在進行寫入時在線完成:
我的期望是最后一步會相對較快,但我真的沒有這個數字。 在我的測試中,大約需要 30 秒。 我想知道我的期望是否不正確,或者我在約束或其他方面做錯了什么。
這是 DDL 的簡化版本。
首先, inserted_at
列聲明如下:
inserted_at timestamp without time zone not null
即使在刪除現有查詢和寫入的 PK 之后,我也希望在 ID 上建立索引,因此我創建了一個索引:
create unique index concurrently my_events_temp_id_index on my_events (id);
檢查約束在一個事務中創建:
alter table my_events add constraint my_events_2022_07_events_check
check (inserted_at >= '2018-01-01' and inserted_at < '2022-08-01')
not valid;
在下一個事務中,它被驗證(並且驗證成功):
alter table my_events validate constraint my_events_2022_07_events_check;
然后在創建分區表之前,我刪除現有表的主鍵:
alter table my_events drop constraint my_events_pkey cascade;
最后,在它自己的事務中,創建分區表:
alter table my_events rename to my_events_2022_07;
create table my_events (
id uuid not null,
... other columns,
inserted_at timestamp without time zone not null,
primary key (id, inserted_at)
) partition by range (inserted_at);
alter table my_events attach partition my_events_2022_07
for values from ('2018-01-01') to ('2022-08-01');
最后一個事務阻塞了我的測試數據庫中 12M 行的插入並花費了大約 30 秒。
編輯
我想添加它以響應我看到的attach
:
信息:現有約束隱含表“my_events_2022_07”的分區約束
這讓我覺得我這樣做是對的。
問題不在於檢查約束,而在於主鍵。
如果您使原始唯一索引包含兩列:
create unique index concurrently my_events_temp_id_index on my_events (id,inserted_at);
而且,如果您使新表在這兩列上具有唯一索引而不是主鍵,那么附加幾乎是瞬時的。
這些在我看來像是 PostgreSQL 中不需要的限制,一列上的唯一索引不能用於暗示兩列的唯一性,並且兩列上的唯一索引不能用於暗示主鍵(甚至唯一約束——但只有唯一索引)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.