Postgresql-11 根据多字段创建分区表

1、表分区的意义

随着系统的使用,业务表的数据会变得越来越庞大,当达到一定程度时,会严重影响系统性能,将表分区,可以很好的解决这个问题。分区表的优点包括:

  • (1)大大提高查询性能;对表分区后,查询时会根据相应的查询条件直接对子表进行查询。
  • (2)插入、更新操作的性能更高;插入时,只对子表进行顺序扫描,比扫描整张表高效的多。
  • (3)批量删除时,可以效率更高;对于不需要的数据,可以直接Drop掉整张子表。
  • (4)对于一些使用频率比较低的数据,可以将对应的子表迁移到成本更低的存储介质上面,降低成本。

Important:并不是分区就一定能提高性能,如果表本身比较小,分区的话,只会更加消耗性能,根据官方的建议,当单张表的体积大于当前服务器内存的时候,建议分区。

2、分区的方法

目前pg分区的方法主要有两种,一是利用pg内置的分区组件,二是利用插件pg-partman。pg内置组件只能在才创建表时进行分区,而pg-partman可以将已经有数据的表进行分区,此外,根据网上的一些评测,pg-partman分区后,数据插入的效率更高。网上评测

2.1 postgresql自带分区方法

pg内置有分区的组件,在10.0版本之前,都是通过触发器来进行分区,即插入数据时,根据字段值判断要插入到哪个子表中,效率比较低,而在10.0之后,pg进行了改进,不再需要触发器。pg-11分区方式有RANG、LIST、HASH三种,我们现在使用的是RANGE,所以下面介绍一下pg-11 RANGE方式创建分区表的方法。

  • (1)基本语法
-- 主表
CREATE TABLE table_name ( column_name data_type )
    PARTITION BY RANGE ( { column_name } [, ... ] )
 
-- 子表
CREATE TABLE table_name
    PARTITION OF parent_table
FOR VALUES
    FROM ( { numeric_literal | string_literal | TRUE | FALSE | MINVALUE | MAXVALUE } [, ...] )
      TO ( { numeric_literal | string_literal | TRUE | FALSE | MINVALUE | MAXVALUE } [, ...] ) 
  • (2)创建父表
CREATE TABLE public.country_fence_parent (
  id int4 NOT NULL,
  branch_range_gis_id int4,
  branch_code int4,
  branch_name varchar(50) COLLATE pg_catalog.default,
  busi_type int4,
  cast_type int4,
  rgb varchar(10) COLLATE pg_catalog.default,
  geom geometry(MULTIPOLYGON, 4326),
  fid int4 NOT NULL DEFAULT nextval('country_fence_parent_fid_seq'::regclass)
)PARTITION BY RANGE (busi_type , cast_type);

父表中根据busi_type和cast_type两个字段进行分区;

  • (3)创建子表(方法1)
CREATE TABLE country_fence_child_1_3 PARTITION OF country_fence_parent
FOR VALUES FROM (1,3) TO (1,4);

Tip: 这个地方range的设置,因为是一个范围,所以必须有一个字段的FROM和TO值不能相等,而插入的时候,取值是FROM<=value

  • (4)创建子表(方法2)
CREATE TABLE public.country_fence_child_1_3 (
  id int4 NOT NULL,
  branch_range_gis_id int4,
  branch_code int4,
  branch_name varchar(50) COLLATE pg_catalog.default,
  busi_type int4,
  cast_type int4,
  rgb varchar(10) COLLATE pg_catalog.default,
  geom geometry(MULTIPOLYGON, 4326),
  fid int4 NOT NULL DEFAULT nextval('country_fence_child_1_3_fid_seq'::regclass)
)
ALTER TABLE public.country_fence_parent ATTACH PARTITION public.country_fence_child_1_3
FOR VALUES FROM (1,3) TO (1,4);

即先创建子表,然后把子表挂载到父表上面.

Tip: 子表是对外不可见的,但是可以直接通过sql的方式对其进行增删改查。

  • (5) 插入操作 创建完成后,直接对父表进行操作,pg会根据busi_type和cast_type的值自动插入到子表中。
insert into country_fence_parent (id, busi_type, cast_type) values (1, 1 , 3);

插入成功,查看sql的执行计划,会发现:

Limit  (cost=0.00..18.49 rows=100 width=1294)
  ->  Append  (cost=0.00..636.20 rows=3440 width=1294)
        ->  Seq Scan on country_fence_child_1_3  (cost=0.00..44.86 rows=229 width=1376)
              Filter: (busi_type = 1)
        ->  Seq Scan on country_fence_child_1_3  (cost=0.00..574.14 rows=3211 width=1289)
              Filter: (busi_type = 1)

如果创建子表时,没有定义相应的规则,则会报错,比如:

insert into country_fence_parent (id, busi_type, cast_type) values (1, 3 , 1);

报错:

没有找到关系“country_fence_parent”的分区

2.2 pg-partman分区

待完善,请参考 pg_partman/pg_partman.md at master · pgpartman/pg_partman · GitHub

参考文献:

PostgreSQL: Documentation: 11: 5.10. Table Partitioning GitHub - pgpartman/pg_partman: Partition management extension for PostgreSQL PostgreSQL 10 内置分区 vs pg_pathman_weixin_34380781的博客-CSDN博客 PostgreSQL 11 分区表用法及增强_rocklee的专栏-CSDN博客_postgresql11 分区表

你可能感兴趣的:(postgresql,数据库,database)