PostgreSQL分区表(partitioning)应用实例

2024-06-02 17:32

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

 

前言

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

查询性能大幅提升删除历史数据更快可将不常用的历史数据使用表空间技术转移到低成本的存储介质上

那么什么时候该使用分区表呢?官方给出的指导意见是:当表的大小超过了数据库服务器的物理内存大小则应当使用分区表,接下来结合一个例子具体记录一下创建分区表的详细过程。

创建分区表

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

这个需求就是一个典型的按时间创建分区表,首先看一下步骤:<喎�"/kf/ware/vc/" target="_blank" class="keylink">vcD4NCrS0vai4uLHttLS9qG649tfTse2jrMO/uPbX07HttrzKx7zMs9DT2ri4se22qNLl0ru49rnm1PKjqFJ1bGWjqbvytKW3osb3o6hUcmlnZ2Vyo6mjrLDRttTW97HttcTK/b7dsuXI69bYtqjP8rW9us/KyrXEt9bH+LHtDQo8cD7I58nPy/nKvqOs1fvM5bXEtPOyvdbovs231s6q0tTJz8j9uPajrLWxyLu7ub/J0tTT0NK70KnQobXE08W7r7TryqmjrLHIyOe21NPaw7+49rfWx/ijrNTaudi8/NfW19a2zsnPtLS9qNK7uPbL99L9tci1yKGjytfPyMC0v7S12tK7sr0mbWRhc2g7Jm1kYXNoO7S0vai4uLHtoaM8L3A+DQo8cD7U2rS0vai31sf4se3Wrsew06a1sc/ItLS9qNK71cUmbGRxdW87uLix7SZyZHF1bzujrMv509C31sf4se22vLTTy/y8zLPQo6zV4rj2se3W0MO709DK/b7do6zSsrK70qrU2tXiuPax7cnPtqjS5cjOus687LLp1LzK+Lywy/fS/aOsz9bU2s7Sw8e+zc/ItLS9qNXi0fnSu9XFse2jrLWr1q7HsM/IvajSu7j20PLB0KO6PC9wPg0KPHByZSBjbGFzcz0="brush:sql;"> 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://www.chinasem.cn/article/1024627

相关文章

java图像识别工具类(ImageRecognitionUtils)使用实例详解

《java图像识别工具类(ImageRecognitionUtils)使用实例详解》:本文主要介绍如何在Java中使用OpenCV进行图像识别,包括图像加载、预处理、分类、人脸检测和特征提取等步骤... 目录前言1. 图像识别的背景与作用2. 设计目标3. 项目依赖4. 设计与实现 ImageRecogni

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

将Python应用部署到生产环境的小技巧分享

《将Python应用部署到生产环境的小技巧分享》文章主要讲述了在将Python应用程序部署到生产环境之前,需要进行的准备工作和最佳实践,包括心态调整、代码审查、测试覆盖率提升、配置文件优化、日志记录完... 目录部署前夜:从开发到生产的心理准备与检查清单环境搭建:打造稳固的应用运行平台自动化流水线:让部署像

Linux中Curl参数详解实践应用

《Linux中Curl参数详解实践应用》在现代网络开发和运维工作中,curl命令是一个不可或缺的工具,它是一个利用URL语法在命令行下工作的文件传输工具,支持多种协议,如HTTP、HTTPS、FTP等... 目录引言一、基础请求参数1. -X 或 --request2. -d 或 --data3. -H 或

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

Oracle Expdp按条件导出指定表数据的方法实例

《OracleExpdp按条件导出指定表数据的方法实例》:本文主要介绍Oracle的expdp数据泵方式导出特定机构和时间范围的数据,并通过parfile文件进行条件限制和配置,文中通过代码介绍... 目录1.场景描述 2.方案分析3.实验验证 3.1 parfile文件3.2 expdp命令导出4.总结

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

java中VO PO DTO POJO BO DO对象的应用场景及使用方式

《java中VOPODTOPOJOBODO对象的应用场景及使用方式》文章介绍了Java开发中常用的几种对象类型及其应用场景,包括VO、PO、DTO、POJO、BO和DO等,并通过示例说明了它... 目录Java中VO PO DTO POJO BO DO对象的应用VO (View Object) - 视图对象