按月增加分区,通过pg_cron来每月调度。
参考:https://help.aliyun.com/document_detail/150355.html?spm=a2c4g.11186623.6.1080.6b31157f7509OO
-- 每个月的4号执行指定脚本。
SELECT cron.schedule('* * 4 * *', 'select 1;');
SELECT * FROM pg_partition_tree('tbl_log');
并行分区表智能JOIN(类似MPP)
当两个JOIN的分区表JOIN字段类型一致,并且分区在JOIN字段上,并且分区类型一致(枚举、LIST、范围、HASH),并且分区个数一致。满足这些条件时,PostgreSQL优化器会选择并行分区智能JOIN,子分区各自JOIN子分区。
引用德哥数据:
场景 | 数据量 | 关闭并行 | 开启并行 | 并行度 | 开启并行性能提升倍数 |
---|---|---|---|---|---|
parallel partition table wise agg | 10亿 | 191 秒 | 8 秒 | 24 | 23.9 倍 |
1、为什么需要分区个数一致才能走wise join?
create table tbl_log
(
id serial,
create_time timestamp(0) without time zone,
remark char(1)
) PARTITION BY RANGE (create_time);
CREATE TABLE tbl_log_p201801 PARTITION OF tbl_log FOR VALUES FROM ('2018-01-01') TO ('2018-02-01');
CREATE TABLE tbl_log_p201802 PARTITION OF tbl_log FOR VALUES FROM ('2018-02-01') TO ('2018-03-01');
CREATE TABLE tbl_log_p201802 PARTITION OF tbl_log FOR VALUES FROM ('2018-03-01') TO ('2018-04-01');
CREATE TABLE tbl_log_default PARTITION OF tbl_log DEFAULT;
INSERT INTO tbl_log(id, create_time, remark) VALUES (1, '2018-02-01', 'a');
INSERT INTO tbl_log(id, create_time, remark) VALUES (2, '2018-03-01', 'b');
INSERT INTO tbl_log(id, create_time, remark) VALUES (3, '2018-04-01', 'd');
INSERT INTO tbl_log(id, create_time, remark) VALUES (3, '2020-07-01', 'c');
此时数据:
select * from tbl_log;
-- 结果
1 2018-02-01 00:00:00 a
2 2018-03-01 00:00:00 b
3 2020-07-01 00:00:00 c
3 2018-04-01 00:00:00 d
select * from tbl_log_default;
-- 结果
3 2018-04-01 00:00:00 d
3 2020-07-01 00:00:00 c
do language plpgsql
$$
declare
parti varchar(16);
fromdate varchar(16);
todate varchar(16);
begin
--1、获取当前日期(年月)
select TO_CHAR(NOW() + INTERVAL '1 MONTH', 'YYYYMM') into parti;
select TO_CHAR(NOW() + INTERVAL '1 MONTH', 'YYYY-MM-01') into fromdate;
select TO_CHAR(NOW() + INTERVAL '2 MONTH', 'YYYY-MM-01') into todate;
fromdate = E'\'' || fromdate || E'\'';
todate = E'\'' || todate || E'\'';
raise notice '%',parti;
raise notice '%',fromdate;
raise notice '%',todate;
--2、解绑default分区
ALTER TABLE tbl_log
DETACH PARTITION tbl_log_default;
-- 3、重命名默认表分区
alter table if exists tbl_log_default
rename to tbl_log_default_old;
--4、创建新分区
raise notice '%', format('CREATE TABLE IF NOT EXISTS %s%s PARTITION OF %s FOR VALUES FROM (%s) TO (%s);',
'tbl_log_p', parti,
'tbl_log', fromdate, todate);
execute format('CREATE TABLE IF NOT EXISTS %s%s PARTITION OF %s FOR VALUES FROM (%s) TO (%s);',
'tbl_log_p', parti,
'tbl_log', fromdate, todate);
--5、创建新的default分区
CREATE TABLE tbl_log_default PARTITION OF tbl_log DEFAULT;
--6、把老default分区的数据导入表
INSERT INTO tbl_log SELECT * FROM tbl_log_default_old;
--7、删除老的default分区
drop table tbl_log_default_old;
end;
$$;
SELECT * FROM pg_partition_tree('tbl_log');
-- 结果
tbl_log false 0
tbl_log_p201801 tbl_log true 1
tbl_log_p201802 tbl_log true 1
tbl_log_p201803 tbl_log true 1
tbl_log_default tbl_log true 1
select * from tbl_log;
-- 结果
1 2018-02-01 00:00:00 a
2 2018-03-01 00:00:00 b
3 2020-07-01 00:00:00 c
3 2018-04-01 00:00:00 d
select * from tbl_log_default;
-- 结果
3 2018-04-01 00:00:00 d
3 2020-07-01 00:00:00 c
SELECT * FROM pg_partition_tree('tbl_log');
-- 结果 (增加了分区:tbl_log_p202007)
tbl_log false 0
tbl_log_p201801 tbl_log true 1
tbl_log_p201802 tbl_log true 1
tbl_log_p201803 tbl_log true 1
tbl_log_p202007 tbl_log true 1
tbl_log_default tbl_log true 1
select * from tbl_log;
-- 结果(数据没少)
1 2018-02-01 00:00:00 a
2 2018-03-01 00:00:00 b
3 2020-07-01 00:00:00 c
3 2018-04-01 00:00:00 d
select * from tbl_log_default;
-- 结果(日期为:2020-07-01的数据不在默认分区了)
3 2018-04-01 00:00:00 d
select * from tbl_log_p202007;
-- 结果(日期为:2020-07-01的数据在合适的分区)
3 2020-07-01 00:00:00 c
pg11分区表提升 https://pgdash.io/blog/partition-postgres-11.html
pg_corn 定时任务插件 https://blog.csdn.net/weixin_42911965/article/details/90670226