postgre sql 将非分区表转化为分区表,动态创建和删除分区

说明:postgresql 数据库表具有dt字段,存‘20220916’,‘20220914’ 值作为分区字段使用,但未真正建立对应物理上的分区,随着时间的推移数据量变大,执行逐渐变慢,开始创建分区表将原有的非分区表转化为分区表。

-- 将原有的非分区表转化为分区表
CREATE OR REPLACE FUNCTION "table_migration" ( "tb_name" VARCHAR, "partition_column" VARCHAR ) RETURNS "pg_catalog"."void" AS $BODY$ DECLARE
DECLARE old_name TEXT := tb_name || '_old';
DECLARE d VARCHAR;
DECLARE days VARCHAR [] := ARRAY (
    SELECT
        to_char( DATE ( T ), 'yyyymmdd' ) :: VARCHAR AS DAY 
    FROM
        generate_series ( '2022-07-15' :: DATE, '2022-09-15', '1 days' ) AS T 
    );
BEGIN
    IF to_regclass ( tb_name ) IS NOT NULL THEN-- 1. 表重命名
        EXECUTE format ( 'ALTER TABLE %I RENAME TO %I', tb_name, old_name );
        -- 2. 创建分区表
        EXECUTE format ( 'CREATE TABLE %I ( LIKE %s INCLUDING ALL ) PARTITION BY list ( %I )', tb_name, old_name, partition_column );
        -- 3. 创建2022年一年的分区
        foreach d IN ARRAY days loop
            EXECUTE format ( 'create table %I partition of %I for values in (%I)', tb_name || '_' || d, tb_name, d );
        END loop;
        -- 4. 执行数据迁移
        EXECUTE format ( 'insert into %I select * from %I', tb_name, old_name );
        -- 5. 删除原来的表,可以先不做
        -- EXECUTE format ( 'drop table %I', old_name );
    END IF;
END;
$BODY$ LANGUAGE plpgsql VOLATILE COST 100

创建表的一个分区,根据时间动态创建

-- 表创建分区 参数 表名 分区序列 例如: ltc_customer , 20220915 则创建 ltc_customer_20220915 分区表
CREATE or replace FUNCTION createPartitionIfNotExists (tb_name VARCHAR, partiton_val VARCHAR) RETURNS void AS $body$
DECLARE master_name TEXT := tb_name; -- 创建分区表的表名
DECLARE partition_name TEXT := tb_name || '_' || partiton_val; -- 分区的表名称

BEGIN
    -- 判断分区名称是否存在,不存在时才需要创建
    IF to_regclass (partition_name) IS NULL THEN
      -- 执行创建分区
      EXECUTE format (
          'create table %I partition of %I for values in (%s)',
          partition_name,
          master_name,
          partiton_val
      );
    END IF;
END;
$body$ LANGUAGE plpgsql;

删除一个表的分区,根据时间动态删除

-- 删除表分区 例如: ltc_customer_20220915
CREATE or replace FUNCTION deletePartitionIfExists (tb_name_partiton_val VARCHAR) RETURNS void AS $body$
DECLARE master_name TEXT := tb_name_partiton_val; -- 删除分区表 表名

BEGIN
    -- 判断分区名称是否存在,不存在时才需要创建
    IF to_regclass (tb_name_partiton_val) is not null THEN
      -- 执行创建分区
      EXECUTE format ('drop table %s ',tb_name_partiton_val);
    END IF;
END;
$body$ LANGUAGE plpgsql;
    原文作者:高个子男孩
    原文地址: https://blog.csdn.net/qq_41982570/article/details/126878258
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞