PostgreSQL/pgsql自动添加分区子表
网上之前能找到的例子,都是按数量创建分区子表。
而实际业务中,按日期分区应该是主流,如果照搬按数量创建分区子表的话,感觉不太合用,毕竟实施运维人员也不想动脑子,你居然要求不能频繁执行某个函数,然后又要求多久必需执行它一次……
那么,还是应该搞一个按日期创建分区子表的函数,就显得很有必要了。
前段时间就抽空写了这样一个函数,以后项目上可以直接拿来用。
这个函数可以多次执行,而且不会创建过多的分区子表(估计我有精神洁癖),毕竟可以通过 _end_date参数来规范子表的日期范围嘛,贴出来共享给大家。
注释写得比较啰嗦,我也怕时间久了记不清当初的意图,慢慢看哈。
CREATE OR REPLACE FUNCTION append_partition_table(_partition_tablename VARCHAR, _begin_date DATE, _end_date DATE, _partition_type INT, _gaps INT)
RETURNS void
AS
$BODY$
DECLARE -- 分区表子表名_partition_child_name VARCHAR;-- 循环递增变量ii INT DEFAULT 0;-- 计算得出的,假设的分区字段From的值,对应的日期partition_from_date DATE;-- 计算得出的,假设的分区字段To的值,对应的日期,用于判断是否可以退出循环partition_to_date DATE;
BEGIN-- 功能:不使用分区表插件,为PgSQL内置分区表中,为指定分区主表,按天、按月、按年添加分区-- 子表,若不是按[天]分区时,添加的分区子表会比[截止日期]稍大些日期-- 在PostgresSQL v14.1中调试通过-- 说明:-- 1、使用该存储过程时,只是按指定规则生成分区子表的表名并创建,并不能判断该子表名是否-- 为分区主表的子表,即,若该子表名已存在则不建表,若该子表名不存在则创建成指定分区-- 主表的分区子表-- 2、分区子表名未加双引号,不区分大小写,默认为小写-- 分区表子表名 = 主表名 + 分隔符 + 年月日(或者年月,或者年),如,log_all_202001或者log_all_20200201-- 3、分区子表将与分区主表在同一个Schema中,本存储过程并不做特殊处理---- 4、本存储过程自动创建的分区子表,是range分区表,请自行建好主表,建主表Demo如下:-- CREATE TABLE queue (-- qid varchar(50) NOT NULL,-- pati_id varchar(50) NULL,-- pati_name varchar(50) NULL,-- serial_number varchar(100) NULL,-- stateid int4-- validdate date,-- PRIMARY KEY (qid, validdate)-- )-- PARTITION BY range (-- validdate-- );-- 5、因为没找到如何查找现有分区子表的From和To的值,所以只好强行建表了,有知道的麻烦告诉我,谢谢 -- 调用Demo1:SELECT append_partition_table('operation_log', '2021-02-11', '2021-08-11', 0, 1);-- 调用Demo2:SELECT append_partition_table('public.operation_log', '2021-02-11', '2021-08-11', 1, 1);-- 参数:_partition_tablename:创建分区子表的主表的名称, 注意确认表名中是否需要包含Schema名,分区
-- 分区子表将与分区主表在同一个Schema中
-- 参数:_begin_date:创建分区表的开始日期
-- 参数:_end_date:创建分区表的截止日期
-- 参数:_partition_type:分区类型[0按天分区,1按月分区,2按年分区]
-- 参数:_gaps:分区间隔,如果分区类型为0,则表示每个分区的间隔为 gaps天
-- 如果分区类型为1,则表示每个分区的间隔为 gaps月
-- 如果分区类型为2,则表示每个分区的间隔为 gaps年-- 输出调试信息RAISE NOTICE '_partition_type=[%]', _partition_type;RAISE NOTICE '_gaps=[%]', _gaps;-- _partitiontype 只接收0/1/2三种值IF _partition_type not in (0,1,2) THENRAISE EXCEPTION 'The Parameter [_partition_type] is incorrect. Only 0, 1, and 2 are supported!!! '; END IF;partition_from_date := _begin_date::DATE;partition_to_date := _begin_date::DATE;-- 开始循环,判断并自动分区WHILE (partition_to_date <= _end_date) LOOP-- 根据[类型入参],生成准备创建的分区子表的表名IF (_partition_type = 0) THEN-- 每个分区按天递增, 递增gaps天, 计算得到From和To的值,并按From的值生成分区子表名中日期的数字部分partition_from_date = _begin_date::DATE+ CONCAT((i)*_gaps,' day')::INTERVAL;partition_to_date = _begin_date::DATE+ CONCAT((i+1)*_gaps,' day')::INTERVAL;_partition_child_name := to_char(partition_from_date::DATE, 'yyyymmdd');ELSEIF (_partition_type = 1) THEN-- 每个分区按月递增, 递增gaps月, 计算得到From和To的值,并按From的值生成分区子表名中日期的数字部分partition_from_date := date_trunc('MONTH', _begin_date::DATE)+ CONCAT((i)*_gaps, ' MONTH')::INTERVAL;partition_to_date := date_trunc('MONTH', _begin_date::DATE)+ CONCAT((i+1)*_gaps, ' MONTH')::INTERVAL;_partition_child_name := to_char(partition_from_date::DATE, 'yyyymm');ELSE-- 每个分区按年递增, 递增gaps年, 计算得到From和To的值,并按From的值生成分区子表名中日期的数字部分partition_from_date := date_trunc('YEAR', _begin_date::DATE) + CONCAT((i)*_gaps,' YEAR')::INTERVAL;partition_to_date := date_trunc('YEAR', _begin_date::DATE) + CONCAT((i+1)*_gaps,' YEAR')::INTERVAL;_partition_child_name := to_char(partition_from_date::DATE, 'yyyy');END IF;-- 拼接分区表子表名,分区表子表名 = 主表名 + 分隔符 + 年月日(或者年月,或者年)_partition_child_name := _partition_tablename||'_'||_partition_child_name;-- 输出调试信息RAISE NOTICE 'partition_from_date=[%]', partition_from_date;RAISE NOTICE 'partition_to_date=[%]', partition_to_date;RAISE NOTICE '_partition_child_name=[%]', _partition_child_name;-- 快速判断某个表是否存在 -- IF (to_regclass(_partition_child_name) is null) THEN-- END IF;-- CREATE TABLE IF NOT EXISTS _partition_child_name
-- PARTITION OF _partition_tablename
-- FOR VALUES FROM (partition_from_date) TO (partition_to_date);-- 输出调试信息RAISE NOTICE 'Run SQL: CREATE TABLE IF NOT EXISTS % PARTITION OF % FOR VALUES FROM (''%'') TO (''%'') WITH (fillfactor=99);', _partition_child_name, _partition_tablename, partition_from_date, partition_to_date;-- 执行SQL语句,判断指定的表名是否存在,若不存在则创建成指定分区主表的分区子表-- [fillfactor=99]也是我的精神洁癖,会浪费1%的磁盘空间,感觉不爽的朋友请自行去掉execute format('CREATE TABLE IF NOT EXISTS %s PARTITION OF %s FOR VALUES FROM (''%s'') TO (''%s'') WITH (fillfactor=99);',_partition_child_name, _partition_tablename, partition_from_date, partition_to_date);RAISE NOTICE 'Run SQL OK!';-- 递增变量i := i + 1;END LOOP; -- End WhileEND;
$BODY$LANGUAGE plpgsql VOLATILE
测试:
SELECT append_partition_table('kysoft.log_all', '2020-02-01', '2020-02-09', 0, 3);
执行结果(意思一下,不贴图了,中间三个表是上面SQL语句建出来的,另两个是之前建的):
Table Name|schema
log_all_202001 kysoft
log_all_20200201 kysoft
log_all_20200204 kysoft
log_all_20200207 kysoft
log_all_his kysoft
另外,因为没找到如何查找现有分区子表的From和To的值,所以只好强行建表了,有知道的麻烦告诉我,谢谢!
PostgreSQL/pgsql自动添加分区子表相关推荐
- PostgreSQL:创建自增序列id,分区表,分区表子表
文章目录 1)创建自增序列seq 2)创建分区表主表 3)创建分区表子表 4)分区表数据插入 5)分区表查询 1)创建自增序列seq CREATE SEQUENCE if not exists pub ...
- excel中提取月份_在Excel中自动添加月份表
excel中提取月份 Set up a Master sheet in your workbook, and add month sheets automatically, based on that ...
- PostgreSQL 分区表性能优化-分区键
目录 前言 优化过程 数据库版本 总体思路 分区键 前言 近期优化SQL的次数越来越多了,优化的思路可以从SQL结构.执行计划.统计信息.执行计划缓存.索引合理性(数据离散度.联合索引等).程序的数据 ...
- linux自动创建分区,shell编程 自动创建分区
用shell脚本自动添加分区,已实现功能如下: 1.检查扩展分区是否,且是否可以添加,如果可以则把所有的剩余空间设置为扩展分区 2.当扩展分区存在,则输入要添加的分区大小,仅接受大于1的正整数 代码如 ...
- 利用Topshelf搭建Windowns服务实现定期自动添加数据逻辑和原理
一.Topshelf基本配置 using System; using System.Collections.Generic; using System.Linq; using System.Text; ...
- mysql 表分区、按时间函数分区、删除分区、自动添加表分区
mysql 表分区的几种方式: RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区. LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进 ...
- mysql按照时间自动创建分区表_mysql 表分区、按时间函数分区、删除分区、自动添加表分区...
mysql 表分区的几种方式: RANGE分区:基于属于一个给定连续区间的列值,把多行分配给分区. LIST分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进 ...
- mysql 主表存hash和子表的名字_【mysql】mysql分表和表分区详解
为什么要分表和分区? 日常开发中我们经常会遇到大表的情况,所谓的大表是指存储了百万级乃至千万级条记录的表.这样的表过于庞大,导致数据库在查询和插入的时候耗时太长,性能低下,如果涉及联合查询的情况,性能 ...
- Access和SQL server开启表间关系,并实现更新或删除母表数据自动更新或删除子表数据...
1.Access开启表间关系,并实现删除母表数据自动删除子表数据: 在Tables等界面 - > 右键 - > Relationships... -> 弹出Relationships ...
最新文章
- LeetCode 42. Trapping Rain Water--算法题--c++解法
- httpHandlers使用和问题
- 每日一皮:这就是成都马拉松???...
- 高中生活--第1篇--荣辱一身,悲尽兴来
- 两个瓶子水怎样一样多_同事每天比我多睡两个小时!省下70万买了地铁站附近房子 杭州姑娘却感叹买房时一定是脑子进了水……...
- php 读取或导出到Excel / CSV (附utf8、gbk 编码转换)
- 10个最佳jQuery Lightbox效果插件收集
- python deque_python中deque类详解
- (转载)js对象原来也有类、实例属性和原型属性
- lamp mysql数据库设置_LAMP环境搭建图形界面配置MySQL数据库
- mysql中文显示问号,不能识别中文的解决方案
- GDB中打印pthread_internal_t的方法
- html返回顶部动画,基于JavaScript实现回到页面顶部动画代码
- 简单详细的OD破解教程(转)
- IP地址、子网掩码、网络数、主机数、广播地址及其计算方法
- 第一篇博客--大学成长指南
- 光棍.com市场推广策划书(爆笑)
- Arnold Denoise流程
- Go 学习笔记(83)— 编码规范及常用开发技巧
- 当原图片加载失败时,如何让图片加载上我们默认给的图片
热门文章
- 6个面试的经典英文问题
- 身体健康,从情绪健康开始
- 魔兽怀旧服wowlua api获取人物坐标信息
- Windows网络编程 c语言 报错:[Error] ‘bzero‘ was not declared in this scope
- 如何让 AI 像人类一样存有大量记忆?
- 【Python】猎聘网招聘数据爬虫(Python网络爬虫课设简要)
- python计算机二级证书含金量到底高不高?
- CGAL笔记之单元格复合体和多面体篇—三维多面体曲面
- JS三元运算符判断多个条件。
- 中国移动ARM芯片CM32M101A资料下载工具tool下载链接