热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

postgresql之分区表

pg10之后有内置分区表,相对于之前传统分区表更好用---传统分区表--继承表postgres#createtabletbl_log(idint4,create_datedate,

pg10之后有内置分区表,相对于之前传统分区表更好用

---传统分区表

  --继承表

postgres=# create table tbl_log(id int4,create_date date,log_type text);
CREATE TABLE

创建一张子表

postgres=# create table tbl_log_sql (sql text ) inherits(tbl_log);
CREATE TABLE

父表子表都可以插入数据,查看表结构

postgres=# \d+ tbl_log
Table "public.tbl_log"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
-------------+---------+-----------+----------+---------+----------+--------------+-------------
id | integer | | | | plain | |
create_date | date | | | | plain | |
log_type | text | | | | extended | |
Child tables: tbl_log_sql
postgres=# \d tbl_log_sql
Table "public.tbl_log_sql"
Column | Type | Collation | Nullable | Default
-------------+---------+-----------+----------+---------
id | integer | | |
create_date | date | | |
log_type | text | | |
sql | text | | |
Inherits: tbl_log

查看数据
postgres=# insert into tbl_log values (1,'2021-10-19',null);
INSERT 0 1
postgres=# insert into tbl_log_sql values (1,'2021-10-18',null,'select 2');
INSERT 0 1
postgres=# select * from tbl_log;
id | create_date | log_type
----+-------------+----------
1 | 2021-10-19 |
1 | 2021-10-18 |
(2 rows)
postgres=# select * from tbl_log_sql;
id | create_date | log_type | sql
----+-------------+----------+----------
1 | 2021-10-18 | | select 2
(1 row)

通过pg_class确认哪张表

postgres=# select p.relname,p.oid,c.* from tbl_log c,pg_class p where c.tableoid=p.oid;
relname | oid | id | create_date | log_type
-------------+-------+----+-------------+----------
tbl_log | 49173 | 1 | 2021-10-19 |
tbl_log_sql | 49179 | 1 | 2021-10-18 |

只查询父表数据,需要在父表名称前加关键字only

postgres=# select * from only tbl_log;
id | create_date | log_type
----+-------------+----------
1 | 2021-10-19 |

如果没有加only会对父表和所有子表进行操作

postgres=# delete from tbl_log;
DELETE 2
postgres=# select * from tbl_log;
id | create_date | log_type
----+-------------+----------
(0 rows)

 创建传统分区表

注意:



  1. 创建父表,如果父表定义约束,子表也会受到约束,因此除非是全局约束,否则不应该创建在父表上,另外父表不应该写入数据。

  2. 用inherits的方式创建继承表,称之为子表或分区,子表的字段应该与父表保持一致。

  3. 给所有子表创建约束,只有约束条件的数据才能写入对应分区或子表,注意:分区约束不能有重叠。

  4. 给所有子表创建索引,由于继承操作不会继承父表上的索引,因此需要手工创建

  5. 在父表上定义触发器insert,update,delete,将sql分发到对应分区(可选),从应用方可以根据分区处理

  6. 启用consratint_exclusion参数,如果设置成off,则会父表上的sql性能会降低

创建父表

postgres=# create table log_ins(id serial,user_id int4,create_time timestamp(0) without time zone);
CREATE TABLE

创建子表以及给子表创建索引,父表不存储数据,可以不用在父表上创建

postgres=# create table log_ins_history(CHECK (create_time <'2017-01-01')) inherits(log_ins);
CREATE TABLE
postgres=# create table log_ins_201701(CHECK (create_time >= '2017-01-01' and create_time <'2017-02-01')) inherits(log_ins);
CREATE TABLE
postgres=# create table log_ins_201702(CHECK (create_time >= '2017-02-01' and create_time <'2017-03-01')) inherits(log_ins);
CREATE TABLE
postgres=# create table log_ins_201703(CHECK (create_time >= '2017-03-01' and create_time <'2017-04-01')) inherits(log_ins);
CREATE TABLE
postgres=# create table log_ins_201704(CHECK (create_time >= '2017-04-01' and create_time <'2017-05-01')) inherits(log_ins);
CREATE TABLE
postgres=# create table log_ins_201705(CHECK (create_time >= '2017-05-01' and create_time <'2017-06-01')) inherits(log_ins);
CREATE TABLE
postgres=# create table log_ins_201706(CHECK (create_time >= '2017-06-01' and create_time <'2017-07-01')) inherits(log_ins);
CREATE TABLE
postgres=# create table log_ins_201707(CHECK (create_time >= '2017-07-01' and create_time <'2017-08-01')) inherits(log_ins);
CREATE TABLE
postgres=# create table log_ins_201708(CHECK (create_time >= '2017-08-01' and create_time <'2017-09-01')) inherits(log_ins);
CREATE TABLE
postgres=# create table log_ins_201709(CHECK (create_time >= '2017-09-01' and create_time <'2017-10-01')) inherits(log_ins);
CREATE TABLE
postgres=# create table log_ins_201710(CHECK (create_time >= '2017-10-01' and create_time <'2017-11-01')) inherits(log_ins);
CREATE TABLE
postgres=# create table log_ins_201711(CHECK (create_time >= '2017-11-01' and create_time <'2017-12-01')) inherits(log_ins);
CREATE TABLE
postgres=# create table log_ins_201712(CHECK (create_time >= '2017-12-01' and create_time <'2018-01-01')) inherits(log_ins);
CREATE TABLE

postgres=# create index idx_his_ctime on log_ins_history using btree (create_time);
CREATE INDEX
postgres=# create index idx_log_ins_201701_ctime on log_ins_201701 using btree (create_time);
CREATE INDEX
postgres=# create index idx_log_ins_201702_ctime on log_ins_201702 using btree (create_time);
CREATE INDEX
postgres=# create index idx_log_ins_201703_ctime on log_ins_201703 using btree (create_time);
CREATE INDEX
postgres=# create index idx_log_ins_201704_ctime on log_ins_201704 using btree (create_time);
CREATE INDEX
postgres=# create index idx_log_ins_201705_ctime on log_ins_201705 using btree (create_time);
CREATE INDEX
postgres=# create index idx_log_ins_201706_ctime on log_ins_201706 using btree (create_time);
CREATE INDEX
postgres=# create index idx_log_ins_201707_ctime on log_ins_201707 using btree (create_time);
CREATE INDEX
postgres=# create index idx_log_ins_201708_ctime on log_ins_201708 using btree (create_time);
CREATE INDEX
postgres=# create index idx_log_ins_201709_ctime on log_ins_201709 using btree (create_time);
CREATE INDEX
postgres=# create index idx_log_ins_201710_ctime on log_ins_201710 using btree (create_time);
CREATE INDEX
postgres=# create index idx_log_ins_201711_ctime on log_ins_201711 using btree (create_time);
CREATE INDEX
postgres=# create index idx_log_ins_201712_ctime on log_ins_201712 using btree (create_time);
CREATE INDEX

创建触发器函数设置数据插入父表时的路由规则

create or replace function log_ins_insert_trigger()
returns trigger
language plpgsql
AS $function$
begin
if (NEW.create_time <'2017-01-01') THEN
insert into log_ins_history values (NEW.*);
elsif (NEW.create_time >= '2017-01-01' and NEW.create_time<'2017-02-01') THEN insert into log_ins_201701 values (NEW.*);
elsif (NEW.create_time >= '2017-02-01' and NEW.create_time<'2017-03-01') THEN insert into log_ins_201702 values (NEW.*);
elsif (NEW.create_time >= '2017-03-01' and NEW.create_time<'2017-04-01') THEN insert into log_ins_201703 values (NEW.*);
elsif (NEW.create_time >= '2017-04-01' and NEW.create_time<'2017-05-01') THEN insert into log_ins_201704 values (NEW.*);
elsif (NEW.create_time >= '2017-05-01' and NEW.create_time<'2017-06-01') THEN insert into log_ins_201705 values (NEW.*);
elsif (NEW.create_time >= '2017-06-01' and NEW.create_time<'2017-07-01') THEN insert into log_ins_201706 values (NEW.*);
elsif (NEW.create_time >= '2017-07-01' and NEW.create_time<'2017-08-01') THEN insert into log_ins_201707 values (NEW.*);
elsif (NEW.create_time >= '2017-08-01' and NEW.create_time<'2017-09-01') THEN insert into log_ins_201708 values (NEW.*);
elsif (NEW.create_time >= '2017-09-01' and NEW.create_time<'2017-10-01') THEN insert into log_ins_201709 values (NEW.*);
elsif (NEW.create_time >= '2017-10-01' and NEW.create_time<'2017-11-01') THEN insert into log_ins_201710 values (NEW.*);
elsif (NEW.create_time >= '2017-11-01' and NEW.create_time<'2017-12-01') THEN insert into log_ins_201711 values (NEW.*);
elsif (NEW.create_time >= '2017-12-01' and NEW.create_time<'2018-01-01') THEN insert into log_ins_201712 values (NEW.*);
else
raise exception 'create_time out of range. fix the log_ins_insert_tigger() function!';
END if;
return null;
end;
$function$;

函数中的NEW.*是要指向插入的数据行,在父表上定义插入触发器

postgres=# create trigger insert_log_ins_trigger before insert on log_ins for each row execute procedure log_ins_insert_trigger();
CREATE TRIGGER

 触发器知识:

 

 

 

 

 使用分区表

插入数据

postgres=# insert into log_ins(user_id,create_time) select round(100000000*random()),generate_series('2016-12-01'::date,'2017-12-01'::date, '1 minute');;
INSERT 0 0

查看父表数据,子表数据

postgres=# select * from only log_ins limit 2;
id | user_id | create_time
----+---------+-------------
(0 rows)
postgres=# select * from log_ins_201703 limit 2;
id | user_id | create_time
--------+----------+---------------------
129601 | 50525906 | 2017-03-01 00:00:00
129602 | 6842102 | 2017-03-01 00:01:00
(2 rows)

查询父表还是子表,假如检索2017-01-01这一天的数据,查询父表和子表之间的差异

postgres=# explain analyze select * from log_ins where create_time > '2017-01-01' and create_time <'2017-01-02';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
Append (cost=0.00..62.21 rows=1497 2017-01-01 00:00:00'::timestamp without time zone) AND (create_time <'2017-01-02 00:00:00'::timestamp without time zone))
-> Index Scan using idx_log_ins_201701_ctime on log_ins_201701 (cost=0.29..62.21 rows=1496 2017-01-01 00:00:00'::timestamp without time zone) AND (create_time <'2017-01-02 00:00:00'::timestamp without time zone))
Planning time: 0.270 ms
Execution time: 0.224 ms
(7 rows)
postgres=# explain analyze select * from log_ins_201701 where create_time > '2017-01-01' and create_time <'2017-01-02';
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Index Scan using idx_log_ins_201701_ctime on log_ins_201701 (cost=0.29..62.21 rows=1496 2017-01-01 00:00:00'::timestamp without time zone) AND (create_time <'2017-01-02 00:00:00'::timestamp without time zone))
Planning time: 0.072 ms
Execution time: 0.191 ms
(4 rows)

可以看出直接访问子表性能有提升,并发量上去的话效果更明显

constraint_exclusion参数

postgres=# show constraint_exclusion;
constraint_exclusion
----------------------
partition

 

on:所有表都通过约束优化查询;

off:所有表不通过约束优化查询;

partition:只对继承表和union all子查询通过检索约束来优化查询(建议)

添加分区,严格按照以下步骤

--创建分区

postgres=# create table log_ins_201801(like log_ins including all);
CREATE TABLE

--添加约束

postgres=# alter table log_ins_201801 add constraint log_ins_201801_create_time_check CHECK(create_time >='2018-01-01' and create_time<'2018-02-01');
ALTER TABLE

--刷新触发器函数

postgres=# create or replace function log_ins_insert_trigger()
postgres-# returns trigger
postgres-# language plpgsql
postgres-# AS $function$
postgres$# begin
postgres$# if (NEW.create_time <'2017-01-01') THEN
postgres$# insert into log_ins_history values (NEW.*);
postgres$# elsif (NEW.create_time >= '2017-01-01' and NEW.create_time<'2017-02-01') THEN insert into log_ins_201701 values (NEW.*);
postgres$# elsif (NEW.create_time >= '2017-02-01' and NEW.create_time<'2017-03-01') THEN insert into log_ins_201702 values (NEW.*);
postgres$# elsif (NEW.create_time >= '2017-03-01' and NEW.create_time<'2017-04-01') THEN insert into log_ins_201703 values (NEW.*);
postgres$# elsif (NEW.create_time >= '2017-04-01' and NEW.create_time<'2017-05-01') THEN insert into log_ins_201704 values (NEW.*);
postgres$# elsif (NEW.create_time >= '2017-05-01' and NEW.create_time<'2017-06-01') THEN insert into log_ins_201705 values (NEW.*);
postgres$# elsif (NEW.create_time >= '2017-06-01' and NEW.create_time<'2017-07-01') THEN insert into log_ins_201706 values (NEW.*);
postgres$# elsif (NEW.create_time >= '2017-07-01' and NEW.create_time<'2017-08-01') THEN insert into log_ins_201707 values (NEW.*);
postgres$# elsif (NEW.create_time >= '2017-08-01' and NEW.create_time<'2017-09-01') THEN insert into log_ins_201708 values (NEW.*);
postgres$# elsif (NEW.create_time >= '2017-09-01' and NEW.create_time<'2017-10-01') THEN insert into log_ins_201709 values (NEW.*);
postgres$# elsif (NEW.create_time >= '2017-10-01' and NEW.create_time<'2017-11-01') THEN insert into log_ins_201710 values (NEW.*);
postgres$# elsif (NEW.create_time >= '2017-11-01' and NEW.create_time<'2017-12-01') THEN insert into log_ins_201711 values (NEW.*);
postgres$# elsif (NEW.create_time >= '2017-12-01' and NEW.create_time<'2018-01-01') THEN insert into log_ins_201712 values (NEW.*);
postgres$# elsif (NEW.create_time >= '2018-01-01' and NEW.create_time<'2018-02-01') THEN insert into log_ins_201801 values (NEW.*);
postgres$# else
postgres$# raise exception 'create_time out of range. fix the log_ins_insert_tigger() function!';
postgres$# END if;
postgres$# return null;
postgres$# end;
postgres$# $function$;

--所有步骤完成之后,将新分区log_ins_201801继承到父表log_ins

postgres=# alter table log_ins_201801 inherit log_ins;
ALTER TABLE

 



推荐阅读
  • Summarize function is doing alignment without timezone ?
    Hi.Imtryingtogetsummarizefrom00:00otfirstdayofthismonthametric, ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • MySQL语句大全:创建、授权、查询、修改等【MySQL】的使用方法详解
    本文详细介绍了MySQL语句的使用方法,包括创建用户、授权、查询、修改等操作。通过连接MySQL数据库,可以使用命令创建用户,并指定该用户在哪个主机上可以登录。同时,还可以设置用户的登录密码。通过本文,您可以全面了解MySQL语句的使用方法。 ... [详细]
  • 图像因存在错误而无法显示 ... [详细]
  • 合并列值-合并为一列问题需求:createtabletab(Aint,Bint,Cint)inserttabselect1,2,3unionallsel ... [详细]
  • 小程序wxs中的时间格式化以及格式化时间和date时间互转
    本文介绍了在小程序wxs中进行时间格式化操作的问题,并提供了解决方法。同时还介绍了格式化时间和date时间的互相转换的方法。 ... [详细]
  • 本文详细介绍了使用C#实现Word模版打印的方案。包括添加COM引用、新建Word操作类、开启Word进程、加载模版文件等步骤。通过该方案可以实现C#对Word文档的打印功能。 ... [详细]
  • 总结一下C中string的操作,来自〈CPrimer〉第四版。1.string对象的定义和初始化:strings1;空串strings2(s1);将s2初始 ... [详细]
  • angular.element使用方法及总结
    2019独角兽企业重金招聘Python工程师标准在线查询:http:each.sinaapp.comangularapielement.html使用方法 ... [详细]
  • 【爬虫】关于企业信用信息公示系统加速乐最新反爬虫机制
    ( ̄▽ ̄)~又得半夜修仙了,作为一个爬虫小白,花了3天时间写好的程序,才跑了一个月目标网站就更新了,是有点悲催,还是要只有一天的时间重构。升级后网站的层次结构并没有太多变化,表面上 ... [详细]
author-avatar
灬段裝丶緈褔_998
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有