首页 > 数据库 >PostgreSQL中使用动态SQL-实现自动按时间创建表分区

PostgreSQL中使用动态SQL-实现自动按时间创建表分区

时间:2023-06-05 10:23:07浏览次数:48  
标签:PostgreSQL name -- 分区 SQL column strSQL time TG

PostgreSQL中通过继承,可以支持基本的表分区功能,比如按时间,每月创建一个表分区,数据记录到对应分区中。按照官方文档的操作,创建子表和index、修改trigger等工作都必须DBA定期去手动执行,不能实现自动化,非常不方便。

尝试着通过在plpgsql代码中使用动态SQL, 将大表分区的运维操作实现自动化, 并且可以重用.

假设某个表 tbl_partition 中有很多记录, 每一条记录中采集时间的字段名为: gather_time, 需要按照这个时间, 每个月的数据自动记录到一个子表中, 子分区表的名称定义为: tbl_partition_201510之类. 实现方法记录如下:


1. 创建主表结构, 表名称 tbl_partition, 其中的时间字段名: gather_time

CREATE TABLE tbl_partition
(
  id integer,
  name text,
  data numeric,
  gather_time timestamp
);

  

2. 为主表创建触发器, 其中,调用了触发器函数 auto_insert_into_tbl_partition('gather_time')

CREATE TRIGGER insert_tbl_partition_trigger
  BEFORE INSERT
  ON tbl_partition
  FOR EACH ROW
  EXECUTE PROCEDURE auto_insert_into_tbl_partition('gather_time');

  

注: 虽然触发器函数缺省不带参数, 此处调用仍然必须传入时间字段名称作为参数. 否则, 函数将不知道以何字段来对主表分区!

 

3. 创建可重用的触发器函数: auto_insert_into_tbl_partition(  time_column_name )

CREATE OR REPLACE FUNCTION auto_insert_into_tbl_partition()
  RETURNS trigger AS
$BODY$
DECLARE
    time_column_name 	text ;			-- 父表中用于分区的时间字段的名称[必须首先初始化!!]
    curMM 		varchar(6);		-- 'YYYYMM'字串,用做分区子表的后缀
    isExist 		boolean;		-- 分区子表,是否已存在
    startTime 		text;
    endTime		text;
    strSQL  		text;
    
BEGIN
    -- 调用前,必须首先初始化(时间字段名):time_column_name [直接从调用参数中获取!!]
    time_column_name := TG_ARGV[0];
   
    -- 判断对应分区表 是否已经存在?
    EXECUTE 'SELECT $1.'||time_column_name INTO strSQL USING NEW;
    curMM := to_char( strSQL::timestamp , 'YYYYMM' );
    select count(*) INTO isExist from pg_class where relname = (TG_RELNAME||'_'||curMM);
 
    -- 若不存在, 则插入前需 先创建子分区
    IF ( isExist = false ) THEN  
        -- 创建子分区表
        startTime := curMM||'01 00:00:00.000';
        endTime := to_char( startTime::timestamp + interval '1 month', 'YYYY-MM-DD HH24:MI:SS.MS');
        strSQL := 'CREATE TABLE IF NOT EXISTS '||TG_RELNAME||'_'||curMM||
                  ' ( CHECK('||time_column_name||'>='''|| startTime ||''' AND '
                             ||time_column_name||'< '''|| endTime ||''' )
                          ) INHERITS ('||TG_RELNAME||') ;'  ;  
        EXECUTE strSQL;
 
        -- 创建索引
        strSQL := 'CREATE INDEX '||TG_RELNAME||'_'||curMM||'_INDEX_'||time_column_name||' ON '
                  ||TG_RELNAME||'_'||curMM||' ('||time_column_name||');' ;
        EXECUTE strSQL;
       
    END IF;
 
    -- 插入数据到子分区!
    strSQL := 'INSERT INTO '||TG_RELNAME||'_'||curMM||' SELECT $1.*' ;
    EXECUTE strSQL USING NEW;
 
    RETURN NULL; 
END
$BODY$
  LANGUAGE plpgsql;

  

说明:
(1) 代码中使用了 TG_ARGV[0] 来获取调用时传入的参数: 用于分区的时间字段名.

(2) 代码中,通过内置参数 TG_RELNAME 获得了父表的表名称.

(3) 首先根据插入时间, 判断对应分区表是否存在? 若存在, 直接插入对应分区子表

(4) 若分区表还不存在, 先创建分区子表和索引, 然后插入数据到所建的子表中.

 

删除表:

drop table xxx cascade


以上代码, 在PostgreSQL v9.4 中调试通过. 理论上, v8.4以上均支持.

 

 

按年份

CREATE OR REPLACE FUNCTION auto_insert_by_year()
  RETURNS trigger AS
$BODY$
DECLARE
    time_column_name    text ;          -- 父表中用于分区的时间字段的名称[必须首先初始化!!]
    curMM       varchar(4);     -- 'YYYY'字串,用做分区子表的后缀
    isExist         boolean;        -- 分区子表,是否已存在
    startTime       text;
    endTime     text;
    strSQL          text;
     
BEGIN
    -- 调用前,必须首先初始化(时间字段名):time_column_name [直接从调用参数中获取!!]
    time_column_name := TG_ARGV[0];
    
    -- 判断对应分区表 是否已经存在?
    EXECUTE 'SELECT $1.'||time_column_name INTO strSQL USING NEW;
    curMM := to_char( strSQL::timestamp , 'YYYY' );
    select count(*) INTO isExist from pg_class where relname = (TG_RELNAME||'_'||curMM);
  
    -- 若不存在, 则插入前需 先创建子分区
    IF ( isExist = false ) THEN 
        -- 创建子分区表
        startTime := curMM||'01 00:00:00.000';
        endTime := to_char( startTime::timestamp + interval '1 month', 'YYYY-MM-DD HH24:MI:SS.MS');
        strSQL := 'CREATE TABLE IF NOT EXISTS '||TG_RELNAME||'_'||curMM||
                  ' ( CHECK('||time_column_name||'>='''|| startTime ||''' AND '
                             ||time_column_name||'< '''|| endTime ||''' )
                          ) INHERITS ('||TG_RELNAME||') ;'  ; 
        EXECUTE strSQL;
  
        -- 创建索引
        strSQL := 'CREATE INDEX '||TG_RELNAME||'_'||curMM||'_INDEX_'||time_column_name||' ON '
                  ||TG_RELNAME||'_'||curMM||' ('||time_column_name||');' ;
        EXECUTE strSQL;
        
    END IF;
  
    -- 插入数据到子分区!
    strSQL := 'INSERT INTO '||TG_RELNAME||'_'||curMM||' SELECT $1.*' ;
    EXECUTE strSQL USING NEW;
  
    RETURN NULL;
END
$BODY$
  LANGUAGE plpgsql;

  

标签:PostgreSQL,name,--,分区,SQL,column,strSQL,time,TG
From: https://www.cnblogs.com/pythonClub/p/17457159.html

相关文章

  • mysql 递归查询父级下的所有子级
    有一张组织表,该表有上下层级,使用mysql递归查询某个组织下的所有子组织,sql要怎么写?假设这张表名为organization的表,其结构如下:CREATETABLEorganization(idINTPRIMARYKEY,nameVARCHAR(50),parent_idINT);表里插入了几条数据INSERTINTO`organization`(`......
  • Springboot 链接DataSource前检查或创建库,并设置时区及sql_mode
    /**Copyright(c)2022.AsiacomTechnologyInc.Allrightsreserved*/importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Configuration;......
  • MySQL学习从基础开始
    1.什么是数据库DataBase,简称DB;数据库软件称为数据库管理系统,英文简称DBMS,全称为DataBaseManagementSystem,例如:Oracle、MySQL、SQLServer、Sybase、informix、DB2等等。2.MySQL概述MySQL最初是由“MySQLAB公司”开发的一套关系型数据库管理系统(RDBMS-RelationDataBas......
  • NoSQL数据库的四大分类的分析
    1NoSQL数据库的四大分类2共同特征对于NoSQL并没有一个明确的范围和定义,但是他们都普遍存在下面一些共同特征:不需要预定义模式:不需要事先定义数据模式,预定义表结构。数据中的每条记录都可能有不同的属性和格式。当插入数据时,并不需要预先定义它们的模式。无共享架构:相对于将所有数据......
  • 基于JAVA操作系统在线网站SQL
    随着21世纪的到来,人们更深刻的感受到了计算机在生活和工作中作用的重要,越来越多的职业需要具有计算机的应用技能。掌握计算机是职业的需要,社会的需要,更是事业发展的需要。今天,计算机技术不但广泛地应用在办公自动化中,还全面参与到各行各业。所有与计算机相关的职业都要求工作者有......
  • sql中,where和having的区别
    区别1:WHERE可以直接使用表中的字段作为筛选条件,但不能使用分组中的计算函数作为筛选条件;HAVING必须要与GROUPBY配合使用,可以把分组计算的函数和分组字段作为筛选条件。这决定了,在需要对数据进行分组统计的时候,HAVING可以完成WHERE不能完成的任务。这是因为,在查询语法结......
  • mysql备忘录
    MySQL8下载安装腾讯云Ubuntu20.04服务器下载MySQL8并开启远程服务下载sudoaptupdate#更新Ubuntu存储库sudoaptinstallmysql-server#下载mysqlsudosystemctlstatusmysql#查看mysql状态配置启动找到mysqld文件路径find/-namemysql.server或find/-namemy......
  • GreatSQL 8.0.32-24 今日发布
    1.新增特性1.1SQL兼容性1.2MGR1.3性能优化1.4安全2.稳定性提升3.其他调整4.bug修复5.GreatSQLVSMySQL6.GreatSQLReleaseNotesGreatSQL8.0.32-24版本发布,增加并行loaddata、(逻辑&CLONE)备份加密、MGR读写节点可绑定动态VIP、Oracle兼容扩......
  • 完整支持Oracle PL/SQL,星环科技KunDB高兼容性实现低成本国产化替代
    从中兴、华为等一系列高新科技企业被美国制裁,到俄乌冲突事件爆发后,西方各国相继宣布制裁俄罗斯,以Oracle、IBM、微软、SAP为代表的科技巨头暂停在俄服务,这一系列动作给我们敲响了加速国产化替代的警钟。数据库作为提供数据存储与处理能力的基础软件,是信息系统的基础、信息安全的基石......
  • Mysql数据备份
    导出库/表导出库:mysqldump-h主机-u用户-p密码数据库>目标路径导出表:mysqldump-h主机-u用户-p密码数据库表1表2表3...>目标路径例如:mysqldump-hlocalhost-uroot-p123456schoolt_studentt_grade>D:/sql/1.sql导入表/库(建议)如果在登录情况下,......