oracle pgsql分区表,postgres实现分区表功能

PG没有类似ORACLE的分区表功能,但它可以通过继承来实现这一功能。

CREATE TABLE t1 (like t

including all) INHERITS (t);

这样,表t的结构,包括索引和约束,都被t1继承了。

一般的应用经常会根据时间字段来做分区,假设一张总表t,它的分表一般为t_yyyymm或t_yyyymmdd,按月或按天分表。

在对历史数据做维护的时候,我们可以只维护分表,而不动到总表。

这里特别需要注意,如果要清理数据数据,用truncate命令,truncate table

t_yyyymm是不行的,这样会导致总表的数据(即所有分区的数据)都被清理掉。

可以在命令里加上only来限制它只删除分表的数据:truncate table only t_yyyymm

PG的分区表有个限制,用以下例子说明:

create table t(id integer,pdate timestamp without time

zone);

CREATE TABLE t_201301 (like t

including all) INHERITS (t);

CREATE TABLE t_201302 (like t

including all) INHERITS (t);

CREATE TABLE t_201303 (like t

including all) INHERITS (t);

CREATE TABLE t_201304 (like t

including all) INHERITS (t);

CREATE TABLE t_201305 (like t

including all) INHERITS (t);

select * from t where pdate>='20130101' and

p_date

这样PG会扫描所有的分区(ORACLE不同,会自动对应到相应分区)

我们可以通过设置参数以及为分表的pdate字段增加check约束来实现分区对应的功能。

SET constraint_exclusion = on;

create table t(id integer,pdate timestamp without time

zone);

create table t_201301 (check (pdate>=date'2013-01-01' and

pdate

create table t_201302 (check (pdate>=date'2013-02-01' and

pdate

create table t_201303 (check (pdate>=date'2013-03-01' and

pdate

create table t_201304 (check (pdate>=date'2013-04-01' and

pdate

create table t_201305 (check (pdate>=date'2013-05-01' and

pdate

select * from t where pdate>='20130101' and

p_date

这样,上述SQL只扫描t_201301和201302。

当对t进行dml操作的时候,例:insert into t

values(9,'20130301');数据只会进入t,不会进入t_201303。我们可以通过对表创建trigger来实现插入的数据自动进入对应的分表。

CREATE OR REPLACE FUNCTION p_insert_trigger()

RETURNS TRIGGER AS $$

BEGIN

IF ( NEW.pdate >= DATE '2013-01-01' AND NEW.pdate < DATE

'2013-02-01' ) THEN

INSERT INTO t_201301 VALUES (NEW.*);

ELSIF ( NEW.pdate >= DATE '2013-02-01' AND NEW.pdate < DATE

'2013-03-01' ) THEN

INSERT INTO t_201302 VALUES (NEW.*);

ELSIF ( NEW.pdate >= DATE '2013-03-01' AND NEW.pdate < DATE

'2013-04-01' ) THEN

INSERT INTO t_201303 VALUES (NEW.*);

ELSIF ( NEW.pdate >= DATE '2013-04-01' AND NEW.pdate < DATE

'2013-05-01' ) THEN

INSERT INTO t_21304 VALUES (NEW.*);

ELSIF ( NEW.pdate >= DATE '2013-05-01' AND NEW.pdate < DATE

'2013-06-01' ) THEN

INSERT INTO t_201305 VALUES (NEW.*);

ELSE

RAISE EXCEPTION 'Date out of range. Fix the p_insert_trigger()

function!';

END IF;

RETURN NULL;

END;

$$

LANGUAGE plpgsql;

CREATE TRIGGER t_trigger_insert

BEFORE INSERT ON t

FOR EACH ROW EXECUTE PROCEDURE p_insert_trigger();

update和delete操作方法相同,语法参考上面例子。

虽然可以通过check

constraint和trigger来实现ORACLE分区表的功能,但在生产环境中,我们是严禁这么做的。以INSERT为例,这样做的结果,比把数据直接插入表中,效率慢了10倍以上!!!所以我们要求在应用程序中通过动态SQL,根据当前日期拼接出数据所要进入的分表表名,再把数据直接插入到分表中。

最后再解释下constraint_exclusion 参数。

constraint_exclusion 为enum类型,一共有3个可选值

on:检查所有表的constraint

off:不检查所有表的constraint

partition:default值,只检查inheritance表和union all

subquery的constarint

该参数只被check constraint驱动,所以要想它起作用必须在分区表上加上check constraint

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值