Postgresql

使用預設分區中已存在的值創建新表分區

  • April 7, 2020

我有下表:

CREATE TABLE orders
(
 info_date  date,
 country_code  VARCHAR,
 order_total   int,
 CONSTRAINT orders_pk PRIMARY KEY (info_date, country_code)
) PARTITION BY LIST (country_code);

CREATE TABLE orders_def PARTITION OF orders DEFAULT;

我插入了一些行,country_code 'foo'它們最終出現在預設分區中。

一段時間後,我決定'foo'值得擁有自己的分區,我該怎麼做?

根據文件:

如果存在 DEFAULT 分區,則如果 DEFAULT 分區中有任何行,則無法添加新分區,否則它們將適合正在添加的新分區。


這是我的嘗試

begin;
CREATE TEMP TABLE temp_table ON COMMIT DROP AS 
SELECT * FROM orders where country_code = 'foo';
DELETE FROM orders where country_code = 'foo';
CREATE TABLE orders_foo PARTITION OF orders FOR VALUES IN ('foo');
INSERT INTO orders_foo select * from temp_table;
commit;

但它似乎是一個黑客。

非黑客將首先不進入這種情況,當您不確定這是否是您想要的永久分區時不使用預設分區。當我們無法正確預見未來時,有時我們不得不求助於黑客。

您可以通過填充一個永久表,然後將其作為新分區附加,而不是使用臨時表來處理數據的出入,從而稍微減少黑客攻擊。

begin;
CREATE TABLE orders_foo (like orders); 
INSERT into orders_foo SELECT * FROM orders where country_code = 'foo';
DELETE FROM orders where country_code = 'foo';
ALTER TABLE orders ATTACH PARTITION orders_foo FOR VALUES IN ('foo');
commit;

您也可以將 INSERT 和 DELETE 組合到一個語句中,但我不知道這真的會給您帶來任何有價值的東西,除了避免一次拼錯“foo”的機會。

with t as (delete from orders where country_code='foo' returning *) 
  insert into  orders_bar select * from t;

引用自:https://dba.stackexchange.com/questions/264463