PostgreSQL之分区表(partitioning)

PostgreSQL之分区表(partitioning)

通过合理的设计,可以选择一定的规则将大表分成多个子表,不重不缺。这就是传说中的分区。比如我们可以按时间划分,每天一个子表。比如我们可以用其他一些字段来划分,简而言之,我们可以把它分成几个部分,提高查询的效率。

PostgreSQL有一个很有用的函数,分区表,或者说分区。当一个表中有很多记录,几千万甚至更多的时候,我们实际上需要把它分成子表。一张巨大的桌子,就像一个水果仓库,无数的苹果、桃子、橘子杂乱地堆放着,不方便寻找,性能降低。把仓库分成三个分区,苹果、桃子、橙子分别放在不同的桌子上,这样比较合理。一个大桌子变成了三个小桌子的集合。

通过合理的设计,可以选择一定的规则将大表分成多个子表,不重不缺。这就是传说中的分区。比如我们可以按时间划分,每天一个子表。比如,我们可以根据其他领域来划分。简而言之就是分成几部分,提高查询效率。

这个分区表的功能是怎么实现的?

1建立大表。

2创建分区继承

3定义规则还是触发器?

下面根据一个简单的例子来描述这个过程。我们按照60分以下和不低于60分把学生分成两个子表。

1 建立大表

创建表student (student_id bigserial,name varchar(32),score smallint)

2 创建分区继承。

创建表student _ qualified(CHECK(score=60))INHERITS(student);

创建表student_nqualified (CHECK(分数60))INHERITS(student);

创建了两个分区表student_qualified和student _ qualified,它们继承了大表student的所有字段,并设置了约束,即检查条件。

3 定义Rule或者Trigger。

虽然我们定义了检查条件,但是在向student中插入数据时,PostgreSQL无法根据分数是否低于60插入正确的子表。原因是您没有定义这个规则来告诉数据这样做。我们需要定义规则或触发器来将数据插入正确的分区表。

先看规则的定义:

创建或替换规则insert_student_qualified

学生插页上的

其中得分=60

改为做

插入student_qualified值(新。*);

创建或替换规则insert_student_nqualified

学生插页上的

其中得分60

改为做

插入到student_nqualified值(新。*);

这两个规则告诉PostgreSQL,在向通用表中插入数据时,如果分数为60,则插入student_qualified,如果分数为60,则插入student _ qualified。注意这个划分一定要准确。如果我们不小心把=60条件的“=”丢掉了,等于60分的记录就会被录入大表学生,这个是没有的。

我们插入一些记录:

插入学生(姓名,分数)值( Jim ,77);

插入学生(姓名,分数)值( Frank ,56);

插入到学生(姓名,分数)值( Bean ,88);

插入学生(姓名,分数)值( John ,47);

插入学生(姓名,分数)值( Albert , 87 );

插入到学生(姓名,分数)值中(“Joey”,“60”);

我们来看看数据分布,是否分布到正确的分区表:

SELECT p.relname,c.tableoid,c.*

来自学生c,pg_class p

其中c.tableoid=p.oid

输出如下所示:

我们可以看到,虽然我们插入的是一个大表,但是数据有对应的分区子表。满足我们的期望。同时也不影响查询。

Rule是一种导流方式,TRIGGER也可以让正确的数据流向正确的分区子表。

我们先定义一个函数。

创建或替换函数student_insert_trigger()

将触发器返回为

$$

开始

IF(NEW.score=60)然后

插入student_qualified值(新。*);

其他

插入到student_nqualified值(新。*);

结束IF;

返回NULL

结束;

$$

语言plpgsql

然后定义触发器,该触发器将在插入学生时触发:

创建触发器insert_student

在插入学生之前

对于每一行

执行过程学生_插入_触发器();

我们首先通过删除桌生,测试下引发方式。

下降表学生级联

创建表学生(student_id bigserial,name varchar(32),score smallint);

创建表student _ qualified(CHECK(分数=60))INHERITS(学生);

创建表学生_不合格(检查(分数60))继承(学生);

然后执行定义功能和定义引发的语句。就可以查看了。

为了确认我们的触发器的确触发了,我们打开存储过程的统计开关:

在postgresql.conf中,找到轨道_功能,改成全部

轨道_功能=全部

插入之前先看下函数学生_插入_触发器的统计信息:

执行插入:

插入学生(姓名,分数)值(‘吉姆’,77);

插入学生(姓名,分数)值(‘弗兰克’,56);

插入到学生(姓名,分数)值(‘豆’,88);

插入学生(姓名,分数)值(‘约翰’,47);

插入学生(姓名,分数)值(‘艾伯特’,‘87’);

插入到学生(姓名,分数)值中(《乔伊》,《60》);

插入后,看下函数学生_插入_触发器的统计信息

我们看到引发触发了6次。

执行下查询:

SELECT p.relname,c.tableoid,c.*

来自学生丙、pg _级

其中c.tableoid=p.oid

输出如下:

参考文献

一个一种数据库系统文档

PostgreSQL之分区表(partitioning)