PostgreSQL分区表(partitioning)应用实例详解

2024-09-08 00:58

本文主要是介绍PostgreSQL分区表(partitioning)应用实例详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

https://www.jb51.net/article/97937.htm

 

PostgreSQL分区表(partitioning)应用实例详解

 更新时间:2016年11月22日 10:25:58   作者:小灯光环    我要评论

 

这篇文章主要为大家详细介绍了PostgreSQL分区表(partitioning)应用实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

前言

项目中有需求要垂直分表,即按照时间区间将数据拆分到n个表中,PostgreSQL提供了分区表的功能。分区表实际上是把逻辑上的一个大表分割成物理上的几小块,提供了很多好处,比如:

1、查询性能大幅提升
2、删除历史数据更快
3、可将不常用的历史数据使用表空间技术转移到低成本的存储介质上
那么什么时候该使用分区表呢?官方给出的指导意见是:当表的大小超过了数据库服务器的物理内存大小则应当使用分区表,接下来结合一个例子具体记录一下创建分区表的详细过程。

创建分区表

首先看一下需求,现在有一张日志表,现在需要按表中的操作时间字段(operation_time)分区,如下图: 

这个需求就是一个典型的按时间创建分区表,首先看一下步骤:

1.创建父表
2.创建n个子表,每个子表都是继承于父表
3.定义一个规则(Rule)或触发器(Trigger),把对主表的数据插入重定向到合适的分区表

如上所示,整体的大步骤就分为以上三个,当然还可以有一些小的优化措施,比如对于每个分区,在关键字字段上创建一个索引等等。首先来看第一步——创建父表。

在创建分区表之前应当先创建一张“父表”,所有分区表都从它继承,这个表中没有数据,也不要在这个表上定义任何检查约束及索引,现在我们就先创建这样一张表,但之前先建一个序列:

?

1

2

3

4

5

6

7

8

CREATE SEQUENCE "public"."t_sys_log_main_id_seq"

 INCREMENT 1

 MINVALUE 1

 MAXVALUE 99999999

 START 1

 CACHE 1;

 

ALTER TABLE "public"."t_sys_log_main_id_seq" OWNER TO "postgres";

接下来创建“父表”,因为是日志表,所以表名命名为“t_sys_log_main”:

 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

CREATE TABLE "public"."t_sys_log_main" (

"id" int4 DEFAULT nextval('t_sys_log_main_id_seq'::regclass) NOT NULL,

"account_affiliation_code" varchar(100) COLLATE "default" NOT NULL,

"account_affiliation" varchar(50) COLLATE "default" NOT NULL,

"operation_time" timestamp(6) NOT NULL,

"operation_key" varchar(2) COLLATE "default" NOT NULL,

"operation_value" varchar(30) COLLATE "default" NOT NULL,

"operation_loginid" varchar(100) COLLATE "default" NOT NULL,

"operation_message" varchar(300) COLLATE "default" NOT NULL,

"operation_ip" varchar(30) COLLATE "default" NOT NULL

)

WITH (OIDS=FALSE)

 

;

COMMENT ON TABLE "public"."t_sys_log_main" IS '系统日志表';

COMMENT ON COLUMN "public"."t_sys_log_main"."account_affiliation_code" IS '帐号所属机构代码';

COMMENT ON COLUMN "public"."t_sys_log_main"."account_affiliation" IS '帐号所属机构';

COMMENT ON COLUMN "public"."t_sys_log_main"."operation_time" IS '操作时间';

COMMENT ON COLUMN "public"."t_sys_log_main"."operation_key" IS '操作类型(key)';

COMMENT ON COLUMN "public"."t_sys_log_main"."operation_value" IS '操作类型(value)';

COMMENT ON COLUMN "public"."t_sys_log_main"."operation_loginid" IS '操作帐号';

COMMENT ON COLUMN "public"."t_sys_log_main"."operation_message" IS '操作信息';

COMMENT ON COLUMN "public"."t_sys_log_main"."operation_ip" IS '登录地址';

 

ALTER TABLE "public"."t_sys_log_main" ADD PRIMARY KEY ("id");

运行以上DDL语句创建父表,创建成功后接下来就可以挨个创建分区表了,由于每个分区表都是从父表继承的,所以分区表不会增加任何字段,下面我们按需求创建4张分区子表,分别用于存放9月、10月、11月和12月的日志数据:

 

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

create table t_sys_log_y2016m09

(CHECK (operation_time >= DATE '2016-09-01' AND operation_time< DATE '2016-10-01'))

INHERITS (t_sys_log_main);

 

create table t_sys_log_y2016m10

(CHECK (operation_time >= DATE '2016-10-01' AND operation_time< DATE '2016-11-01'))

INHERITS (t_sys_log_main);

 

create table t_sys_log_y2016m11

(CHECK (operation_time >= DATE '2016-11-01' AND operation_time< DATE '2016-12-01'))

INHERITS (t_sys_log_main);

 

create table t_sys_log_y2016m12

(CHECK (operation_time >= DATE '2016-12-01' AND operation_time< DATE '2017-01-01'))

INHERITS (t_sys_log_main);

如上所示,运行完成后即可创建4张分区子表,在上面的语句中我们添加了一个约束表示只允许插入本月的数据,接下来在这4张分区表的每个分区键上建立索引:

?

1

2

3

4

create index t_sys_log_y2016m09_operation_time ON t_sys_log_y2016m09(operation_time);

create index t_sys_log_y2016m10_operation_time ON t_sys_log_y2016m10(operation_time);

create index t_sys_log_y2016m11_operation_time ON t_sys_log_y2016m11(operation_time);

create index t_sys_log_y2016m12_operation_time ON t_sys_log_y2016m12(operation_time);

到此为止我们的分区表就创建完毕了,接下来需要考虑数据插入的问题,如何才能让不同日期的数据自动的插入与其对应的分区子表中呢?有两种解决方案,分别是:规则(Rule)和触发器(Trigger),相比触发器,Rule的开销更大,所以我在这里就不做过多介绍了,下面直接介绍Trigger的方式。

Trigger通常会结合自定义函数(Function)来实现分区插入,Function负责根据条件选择插入,而Trigger则负责Function的自动调用。首先定义Function,功能很简单,即根据日期区间insert数据即可:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

CREATE

OR REPLACE FUNCTION sys_log_insert_trigger () RETURNS TRIGGER AS $$

BEGIN

 

IF (

  NEW .operation_time >= DATE '2016-09-01'

  AND NEW .operation_time < DATE '2016-10-01'

) THEN

  INSERT INTO t_sys_log_y2016m09

VALUES

  (NEW .*) ;

ELSEIF (

  NEW .operation_time >= DATE '2016-10-01'

  AND NEW .operation_time < DATE '2016-11-01'

) THEN

  INSERT INTO t_sys_log_y2016m10

VALUES

  (NEW .*) ;

ELSEIF (

  NEW .operation_time >= DATE '2016-11-01'

  AND NEW .operation_time < DATE '2016-12-01'

) THEN

  INSERT INTO t_sys_log_y2016m11

VALUES

  (NEW .*) ;

ELSEIF (

  NEW .operation_time >= DATE '2016-12-01'

  AND NEW .operation_time < DATE '2017-01-01'

) THEN

  INSERT INTO t_sys_log_y2016m12

VALUES

  (NEW .*) ;

ELSE

  RAISE EXCEPTION 'Date out of range!' ;

END

IF ; RETURN NULL ;

END ; $$ LANGUAGE plpgsql;

最后再创建触发器用于执行刚才的Function:

?

1

2

3

CREATE TRIGGER sys_log_insert_trigger BEFORE INSERT ON t_sys_log_main

FOR EACH ROW

EXECUTE PROCEDURE sys_log_insert_trigger();

到这里就全部创建完成了,最后测试一下看看结果。为了确认我们的触发器的确触发了,我们打开存储过程的统计开关,在postgresql.conf中,找到track_functions,改成all: 

接下来就可以运行几条测试insert语句来看看是否能把指定的时间记录分别插入到与其对应的分区子表中,插入之前先看下sys_log_insert_trigger()的统计信息: 

可以看到目前没有统计记录,接下来插入几条测试数据:

?

1

2

3

4

5

6

7

8

9

10

11

12

INSERT INTO t_sys_log_main VALUES

(1,'200022', '西安高新第一中学初中校区', '2016-9-8 18:49:26.004', '01', 'xx', 'zhsz_t', 'test!', '127.0.0.1');

INSERT INTO t_sys_log_main VALUES

(1,'200023', '西安高新第一中学初中校区', '2016-9-12 18:49:26.004', '01', 'xx', 'zhsz_t', 'test!', '127.0.0.1');

INSERT INTO t_sys_log_main VALUES

(1,'200024', '西安高新第一中学初中校区', '2016-10-8 18:49:26.004', '01', 'xx', 'zhsz_t', 'test!', '127.0.0.1');

INSERT INTO t_sys_log_main VALUES

(1,'200025', '西安高新第一中学初中校区', '2016-11-8 18:49:26.004', '01', 'xx', 'zhsz_t', 'test!', '127.0.0.1');

INSERT INTO t_sys_log_main VALUES

(1,'200026', '西安高新第一中学初中校区', '2016-12-8 18:49:26.004', '01', 'xx', 'zhsz_t', 'test!', '127.0.0.1');

INSERT INTO t_sys_log_main VALUES

(1,'200027', '西安高新第一中学初中校区', '2016-12-25 18:49:26.004', '01', 'xx', 'zhsz_t', 'test!', '127.0.0.1');

紧接着再看一下sys_log_insert_trigger()的统计信息: 

如上图,可以看出调用了6次函数,因为我们插入了6条数据,至此分区表由创建到测试的整个过程就已经成功完成了。

总结

简单记录一下PostgreSQL创建分区表的完整步骤以及注意事项,希望对遇到同样问题的朋友有所帮助,The End。

您可能感兴趣的文章:

  • PostgreSQL之分区表(partitioning)

原文链接:http://blog.csdn.net/wlwlwlwl015/article/details/52419919

这篇关于PostgreSQL分区表(partitioning)应用实例详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1146665

相关文章

Java中Arrays类和Collections类常用方法示例详解

《Java中Arrays类和Collections类常用方法示例详解》本文总结了Java中Arrays和Collections类的常用方法,涵盖数组填充、排序、搜索、复制、列表转换等操作,帮助开发者高... 目录Arrays.fill()相关用法Arrays.toString()Arrays.sort()A

Python 字典 (Dictionary)使用详解

《Python字典(Dictionary)使用详解》字典是python中最重要,最常用的数据结构之一,它提供了高效的键值对存储和查找能力,:本文主要介绍Python字典(Dictionary)... 目录字典1.基本特性2.创建字典3.访问元素4.修改字典5.删除元素6.字典遍历7.字典的高级特性默认字典

MySQL 主从复制部署及验证(示例详解)

《MySQL主从复制部署及验证(示例详解)》本文介绍MySQL主从复制部署步骤及学校管理数据库创建脚本,包含表结构设计、示例数据插入和查询语句,用于验证主从同步功能,感兴趣的朋友一起看看吧... 目录mysql 主从复制部署指南部署步骤1.环境准备2. 主服务器配置3. 创建复制用户4. 获取主服务器状态5

一文详解如何使用Java获取PDF页面信息

《一文详解如何使用Java获取PDF页面信息》了解PDF页面属性是我们在处理文档、内容提取、打印设置或页面重组等任务时不可或缺的一环,下面我们就来看看如何使用Java语言获取这些信息吧... 目录引言一、安装和引入PDF处理库引入依赖二、获取 PDF 页数三、获取页面尺寸(宽高)四、获取页面旋转角度五、判断

Spring Boot中的路径变量示例详解

《SpringBoot中的路径变量示例详解》SpringBoot中PathVariable通过@PathVariable注解实现URL参数与方法参数绑定,支持多参数接收、类型转换、可选参数、默认值及... 目录一. 基本用法与参数映射1.路径定义2.参数绑定&nhttp://www.chinasem.cnbs

MySql基本查询之表的增删查改+聚合函数案例详解

《MySql基本查询之表的增删查改+聚合函数案例详解》本文详解SQL的CURD操作INSERT用于数据插入(单行/多行及冲突处理),SELECT实现数据检索(列选择、条件过滤、排序分页),UPDATE... 目录一、Create1.1 单行数据 + 全列插入1.2 多行数据 + 指定列插入1.3 插入否则更

Redis中Stream详解及应用小结

《Redis中Stream详解及应用小结》RedisStreams是Redis5.0引入的新功能,提供了一种类似于传统消息队列的机制,但具有更高的灵活性和可扩展性,本文给大家介绍Redis中Strea... 目录1. Redis Stream 概述2. Redis Stream 的基本操作2.1. XADD

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

JSONArray在Java中的应用操作实例

《JSONArray在Java中的应用操作实例》JSONArray是org.json库用于处理JSON数组的类,可将Java对象(Map/List)转换为JSON格式,提供增删改查等操作,适用于前后端... 目录1. jsONArray定义与功能1.1 JSONArray概念阐释1.1.1 什么是JSONA

Java JDK1.8 安装和环境配置教程详解

《JavaJDK1.8安装和环境配置教程详解》文章简要介绍了JDK1.8的安装流程,包括官网下载对应系统版本、安装时选择非系统盘路径、配置JAVA_HOME、CLASSPATH和Path环境变量,... 目录1.下载JDK2.安装JDK3.配置环境变量4.检验JDK官网下载地址:Java Downloads