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

相关文章

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

使用IDEA部署Docker应用指南分享

《使用IDEA部署Docker应用指南分享》本文介绍了使用IDEA部署Docker应用的四步流程:创建Dockerfile、配置IDEADocker连接、设置运行调试环境、构建运行镜像,并强调需准备本... 目录一、创建 dockerfile 配置文件二、配置 IDEA 的 Docker 连接三、配置 Do

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

深入浅出SpringBoot WebSocket构建实时应用全面指南

《深入浅出SpringBootWebSocket构建实时应用全面指南》WebSocket是一种在单个TCP连接上进行全双工通信的协议,这篇文章主要为大家详细介绍了SpringBoot如何集成WebS... 目录前言为什么需要 WebSocketWebSocket 是什么Spring Boot 如何简化 We

Java Stream流之GroupBy的用法及应用场景

《JavaStream流之GroupBy的用法及应用场景》本教程将详细介绍如何在Java中使用Stream流的groupby方法,包括基本用法和一些常见的实际应用场景,感兴趣的朋友一起看看吧... 目录Java Stream流之GroupBy的用法1. 前言2. 基础概念什么是 GroupBy?Stream

python中列表应用和扩展性实用详解

《python中列表应用和扩展性实用详解》文章介绍了Python列表的核心特性:有序数据集合,用[]定义,元素类型可不同,支持迭代、循环、切片,可执行增删改查、排序、推导式及嵌套操作,是常用的数据处理... 目录1、列表定义2、格式3、列表是可迭代对象4、列表的常见操作总结1、列表定义是处理一组有序项目的

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

SQL Server 中的 WITH (NOLOCK) 示例详解

《SQLServer中的WITH(NOLOCK)示例详解》SQLServer中的WITH(NOLOCK)是一种表提示,等同于READUNCOMMITTED隔离级别,允许查询在不获取共享锁的情... 目录SQL Server 中的 WITH (NOLOCK) 详解一、WITH (NOLOCK) 的本质二、工作

C#中的Converter的具体应用

《C#中的Converter的具体应用》C#中的Converter提供了一种灵活的类型转换机制,本文详细介绍了Converter的基本概念、使用场景,具有一定的参考价值,感兴趣的可以了解一下... 目录Converter的基本概念1. Converter委托2. 使用场景布尔型转换示例示例1:简单的字符串到