pg12自动创建表分区

pg12自动创建表分区

总体思路

按月增加分区,通过pg_cron来每月调度。

pg_cron

参考:https://help.aliyun.com/document_detail/150355.html?spm=a2c4g.11186623.6.1080.6b31157f7509OO

-- 每个月的4号执行指定脚本。
SELECT cron.schedule('* * 4 * *', 'select 1;')

1、常用操作

查看分区树

SELECT * FROM pg_partition_tree('tbl_log');

2、parallel partition table wise join

并行分区表智能JOIN(类似MPP)

当两个JOIN的分区表JOIN字段类型一致,并且分区在JOIN字段上,并且分区类型一致(枚举、LIST、范围、HASH),并且分区个数一致。满足这些条件时,PostgreSQL优化器会选择并行分区智能JOIN,子分区各自JOIN子分区。

引用德哥数据:

场景 数据量 关闭并行 开启并行 并行度 开启并行性能提升倍数
parallel partition table wise agg 10亿 191 秒 8 秒 24 23.9 倍

问题

1、为什么需要分区个数一致才能走wise join?

3、自动创建表分区

3.1、创建测试表

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

3.2、自动创建分区表过程

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;
$$;

3.3、验证

3.3.1、执行前:
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

3.3.2、执行后:
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

你可能感兴趣的:(postgreSql)