PostgreSQL 動態分表 Rotate輪詢

2021-09-20 10:53:34 字數 2938 閱讀 1920

工作中,遇到如下業務需求:使用者可以自定義歷史資料的儲存期限,且對過期資料不作保留(即定期刪除),該類資料表的數量級在6千萬/年。

前期處理方案:按月分表,由於在專案前期,限制使用者只能儲存一年的資料量,通過pg的rule分表,並通過一張中間表,進行新月份資料的錄入更替。簡單rotate用法,在月份更替零點執行即可,因ddl支援事務,可以對失敗操作進行回滾。

使用rule建立分割槽表的操作不再累述,因為每年有固定的12個月,舉例,當前5月份資料存放在table_***_5表中,那麼去年6月份的資料就存放在table_***_5表中,而去年5月份的資料,存放在table_***_med表中,以便查詢5月剩餘天數在去年的歷史資料,輪詢資料的方法如下:

1. 開始事務

begin;

set lock_timeout = '30's;

2. 查詢nextmonth

select extract(mon from now()) + 1;

3. 刪除table_***_med表約束

alter table table_***_med drop constraint if exists ck_mon;

4. 刪除table_***_med資料

truncate table_***_med;

5. 重新命名table_***_med,以便於將table_***_05重名為table_***_med

alter table table_***_med rename to table_***_med_temp;

alter table table_***_05 rename to table_***_med;

6. 新增約束,重新命名表

alter table table_***_med_temp add constraint ck_mon check ( extract ( mon from crt_time ) = 5 );

alter table table_***_med_temp rename to table_***_05;

7. 提交或回滾

commit;

rollback;

如果對於資料查詢的實時性要求很高,即不能容忍零點時事務執行存在對業務的delay時長,那麼可以再新增一張中間表,為下月資料平滑切換提供儲存空間,在任意業務空閒時間點執行即可。

使用者自定義資料儲存期限方案:

在主表上觸發器,每當有資料插入時,判斷是否存在對應年份+月份的分割槽表,如果存在,則直接插入,如果不存在,則重新建立年份+月份分割槽表,並建立對應索引;對過期月份的分割槽表,直接drop。

不足之處:觸發器是針對each row的,在資料插入方面的效能不及rule形式的表分割槽,但測試得到e3下的插入效率遠大於1k/s,滿足業務場景需求。

具體實現如下:

create or replace function dynamic_create_table_func () returns trigger as $body$

declare

date_catalog text;

sql_statement text;

sql_create text;

sql_index text;

begin

select to_char( new.dp_crt, 'yy_mm' ) into date_catalog;

sql_statement := 'insert into dynamic_partition_table_' || date_catalog || ' (dp_id, dp_content, dp_crt, part_x) values (nextval(''dynamic_partition_table_dp_id_seq''), $1.dp_content, $1.dp_crt, ' || to_char( new.dp_crt, 'yymm' ) || ')';

execute sql_statement using new;

return null;

exception

when undefined_table then

sql_create := 'create table if not exists dynamic_partition_table_' || date_catalog || ' (check(part_x = ' || to_char( new.dp_crt, 'yymm' ) || ')) inherits (dynamic_partition_table);';

execute sql_create;

sql_index := 'create index dynamic_partition_table_' || date_catalog || '_dp_id_idx on dynamic_partition_table_' || date_catalog || '(dp_id);';

execute sql_index;

sql_index := 'create index dynamic_partition_table_' || date_catalog || '_dp_crt_idx on dynamic_partition_table_' || date_catalog || '(dp_crt);';

execute sql_index;

execute sql_statement using new;

return null;

end;

$body$

language'plpgsql';

create trigger dynamic_partition_table_insert_trg before insert on dynamic_partition_table for each row execute procedure dynamic_create_table_func ();

建立的表名格式,table_***_18_05。

各位前輩,晚輩初學pg不才,如有更優的方案,望不吝明示。

R連線postgresql中文亂碼

library rpostgresql pgdriver dbdriver postgresql key dbconnect pgdriver,host 192.168.1.121 port 5432 dbname test project user postgres password 123456...

postgresql表分割槽

pg的表分割槽實際就是所說的分表,pg的表分割槽的是採用繼承表的方式。表繼承所有父表的檢查與約束都會被子表繼承,主外來鍵關係不會。乙個子表可以繼承多個父表,修改父表的表結構時,大多數情況下也會修改子表的結構定義。分割槽表就是把邏輯上的乙個大表分割成物理上的幾個小塊。好處 1 delete資料更快,只...

postgresql使用觸發器進行分表操作

1.首先準備測試的父表 2.建立子表 create table info 2017 check year 2017 inherits info create table info 2018 check year 2018 inherits info 3.建立各表索引 create index inf...