以短暂的锁将准备好的表挂载为分区(ATTACH PARTITION)
PostgreSQL分区命令
-- 1) Prepare the data in a separate table without touching the live table
CREATE TABLE sales_2027_01 (LIKE sales INCLUDING DEFAULTS INCLUDING CONSTRAINTS);
-- ... bulk load (COPY / INSERT) ...
ALTER TABLE sales_2027_01 ADD PRIMARY KEY (id, created_at);
CREATE INDEX CONCURRENTLY sales_2027_01_customer_id_idx ON sales_2027_01 (customer_id);
-- 2) A CHECK that exactly matches the bounds: avoids a full scan during ATTACH
ALTER TABLE sales_2027_01 ADD CONSTRAINT sales_2027_01_bound_chk
CHECK (created_at IS NOT NULL AND created_at >= DATE '2027-01-01' AND created_at < DATE '2027-02-01') NOT VALID;
ALTER TABLE sales_2027_01 VALIDATE CONSTRAINT sales_2027_01_bound_chk;
-- 3) Attach (SHARE UPDATE EXCLUSIVE on the parent; reads/writes continue)
SET lock_timeout = '5s';
ALTER TABLE sales ATTACH PARTITION sales_2027_01
FOR VALUES FROM ('2027-01-01') TO ('2027-02-01');
RESET lock_timeout;
-- 4) Drop the now redundant CHECK
ALTER TABLE sales_2027_01 DROP CONSTRAINT sales_2027_01_bound_chk;作用
利用与边界匹配的预先验证的 CHECK 约束和预先建好的索引,在不进行全量扫描、不长时间加锁的情况下,将加载到单独表中的数据变为一个分区。
适用场景
用于批量加载(ETL)或从归档还原:在不触及在线表的情况下准备数据,然后一步上线。
注意
ATTACH 在父表上获取 SHARE UPDATE EXCLUSIVE,在被挂载的表上获取 ACCESS EXCLUSIVE。如果没有匹配的有效 CHECK,会在该锁下全量扫描表以验证边界;如果缺少与父表匹配的索引,ATTACH 会在锁下创建它们,因此请提前准备好两者。如果存在默认分区,也会扫描它以证明其中没有新范围内的行(参见默认分区操作指南)。列名和类型必须与父表完全一致;用 LIKE ... INCLUDING 创建表是最安全的方式。