爱开发联盟是国内专业的网站建设资源、脚本编程学习类网站,提供asp、php、asp.net、javascript、jquery、vbscript、dos批处理、网页制作、网络编程、网站建设等编程资料。让开发变得简单起来!
爱开发联盟是国内专业的网站建设资源、脚本编程学习类网站,提供asp、php、asp.net、javascript、jquery、vbscript、dos批处理、网页制作、网络编程、网站建设等编程资料。让开发变得简单起来!
当前所在位置:主页 > 数据库 > PostgreSQL >
  • 魔艺客提供SEO\SEM推广整合营销服务
  • 提供整套互联网营销整合方案-魔艺客
  • 魔艺客高端网站建设开发服务十一大优惠服务
  • 资深的网站建设开发经验,一对一服务-魔艺客高
  • 一站式服务,从服务器到网站,三站何以尽在魔
爱开发联盟是国内专业的网站建设资源、脚本编程学习类网站,提供asp、php、asp.net、javascript、jquery、vbscript、dos批处理、网页制作、网络编程、网站建设等编程资料。让开发变得简单起来!

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

发布时间:2017-09-13 23:18    作者:爱开发联盟    浏览:次    来源:aikaifa.com.cn 分享:

前言

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

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

创建分区表

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

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

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

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

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

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”:

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月的日志数据:

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张分区表的每个分区键上建立索引:

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数据即可:

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:

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()的统计信息:

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

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。

网友评论

分类排行榜联系我们

好文推荐联系我们

爱开发联盟是国内专业的网站建设资源、脚本编程学习类网站,提供asp、php、asp.net、javascript、jquery、vbscript、dos批处理、网页制作、网络编程、网站建设等编程资料。让开发变得简单起来!
爱开发联盟是国内专业的网站建设资源、脚本编程学习类网站,提供asp、php、asp.net、javascript、jquery、vbscript、dos批处理、网页制作、网络编程、网站建设等编程资料。让开发变得简单起来!

当前最新内容联系我们

爱开发联盟是国内专业的网站建设资源、脚本编程学习类网站,提供asp、php、asp.net、javascript、jquery、vbscript、dos批处理、网页制作、网络编程、网站建设等编程资料。让开发变得简单起来!

在线手册

网站地图导航

前端 HTML/Xhtml HTML5 CSS XML/XSLT Dreamweaver教程 Frontpage教程 心得技巧 编程 JavaScript ASP.NET PHP编程 正则表达式 AJAX相关 ASP编程 JSP编程 Flex 脚本加解密 web2.0 XML/RSS 网页编辑器 相关技巧 安全相关 网页播放器 Dart 其它综合 脚本 VBS DOS/BAT HTA HTC Python perl 游戏相关 vba 远程脚本 ColdFusion ruby专题 autoit seraphzone PowerShell linux shell Lua Golang Erlang 脚本下载 广告代码 js框架 批处理 网页相关 源码下载 数据库 MsSql Mysql mariadb oracle DB2 mssql2008 mssql2005 SQLite PostgreSQL MongoDB Redis Access 数据库文摘 数据库其它 CMS dedecms ecshop z-blog UcHome UCenter 风讯CMS 科汛cms discuz 新云cms phpwind 动易cms phpcms 帝国cms WordPress drupal 其它cms 设计 photoshop教程 摄影教程 Fireworks教程 CorelDraw教程 Illustrator教程 Painter教程 Freehand教程 Indesign 设计素材 平面其它 微信相关 微信公众号 小程序 操作系统 bios 系统安装 系统进程 Windows系列 LINUX RedHat/Centos Ubuntu/Debian Fedora Solaris 麒麟系统 红旗Linux Unix/BSD 苹果MAC 注册表 其它系统 网站运营 建站经验 微信营销 网站优化 网站策划 网络赚钱 网络创业 站长故事 alexa域名 其它相关 网络安全 黑客教程 安全设置 杀毒防毒 病毒查杀 脚本攻防 黑客入侵 工具使用 业界动态 Exploit 漏洞分析 加密解密 手机黑客 安全其它 在线手册 网页制作 脚本编程 数据库相关 软件编程 系统相关 其它相关 源码下载

友情链接申请加入

51CTO 上海魔艺客 猫鼬设计开发 Erlo网站开发 猫鼬设计工作室 新发现全球资讯 信息安全与IT资讯
爱开发联盟是国内专业的网站建设资源、脚本编程学习类网站,提供asp、php、asp.net、javascript、jquery、vbscript、dos批处理、网页制作、网络编程、网站建设等编程资料。让开发变得简单起来!

283882409