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

相关文章

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

C#读写文本文件的多种方式详解

《C#读写文本文件的多种方式详解》这篇文章主要为大家详细介绍了C#中各种常用的文件读写方式,包括文本文件,二进制文件、CSV文件、JSON文件等,有需要的小伙伴可以参考一下... 目录一、文本文件读写1. 使用 File 类的静态方法2. 使用 StreamReader 和 StreamWriter二、二进

Conda与Python venv虚拟环境的区别与使用方法详解

《Conda与Pythonvenv虚拟环境的区别与使用方法详解》随着Python社区的成长,虚拟环境的概念和技术也在不断发展,:本文主要介绍Conda与Pythonvenv虚拟环境的区别与使用... 目录前言一、Conda 与 python venv 的核心区别1. Conda 的特点2. Python v

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP

java中反射Reflection的4个作用详解

《java中反射Reflection的4个作用详解》反射Reflection是Java等编程语言中的一个重要特性,它允许程序在运行时进行自我检查和对内部成员(如字段、方法、类等)的操作,本文将详细介绍... 目录作用1、在运行时判断任意一个对象所属的类作用2、在运行时构造任意一个类的对象作用3、在运行时判断

PostgreSQL的扩展dict_int应用案例解析

《PostgreSQL的扩展dict_int应用案例解析》dict_int扩展为PostgreSQL提供了专业的整数文本处理能力,特别适合需要精确处理数字内容的搜索场景,本文给大家介绍PostgreS... 目录PostgreSQL的扩展dict_int一、扩展概述二、核心功能三、安装与启用四、字典配置方法

MySQL 中的 CAST 函数详解及常见用法

《MySQL中的CAST函数详解及常见用法》CAST函数是MySQL中用于数据类型转换的重要函数,它允许你将一个值从一种数据类型转换为另一种数据类型,本文给大家介绍MySQL中的CAST... 目录mysql 中的 CAST 函数详解一、基本语法二、支持的数据类型三、常见用法示例1. 字符串转数字2. 数字

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

Mysql实现范围分区表(新增、删除、重组、查看)

《Mysql实现范围分区表(新增、删除、重组、查看)》MySQL分区表的四种类型(范围、哈希、列表、键值),主要介绍了范围分区的创建、查询、添加、删除及重组织操作,具有一定的参考价值,感兴趣的可以了解... 目录一、mysql分区表分类二、范围分区(Range Partitioning1、新建分区表:2、分

MyBatis-Plus 中 nested() 与 and() 方法详解(最佳实践场景)

《MyBatis-Plus中nested()与and()方法详解(最佳实践场景)》在MyBatis-Plus的条件构造器中,nested()和and()都是用于构建复杂查询条件的关键方法,但... 目录MyBATis-Plus 中nested()与and()方法详解一、核心区别对比二、方法详解1.and()