PostgreSQL 17新特性之分区拆分与合并

作者 : admin 本文共2131个字,预计阅读时间需要6分钟 发布时间: 2024-06-10 共1人阅读

PostgreSQL 17 增强了分区管理功能,支持分区的拆分以及合并,同时支持分区表的标识列以及排除约束功能。

本文给大家介绍一下新增的分区拆分(ALTER TABLE … SPLIT PARTITION …)和分区合并(ALTER TABLE … MERGE PARTITIONS …)功能,以及它们的使用限制和注意事项。

我们首先创建一个用于测试的分区表:

CREATE TABLE sales (
  id     bigint generated always as identity,
  area   varchar(10) not null,
  amount numeric not null
) PARTITION BY list (area);

CREATE TABLE sales_north partition OF sales FOR VALUES IN ('华北','东北', '西北');

CREATE TABLE sales_south partition OF sales FOR VALUES IN ( '华东', '中南', '西南');

分区拆分

ALTER TABLE … SPLIT PARTITION … 命令用于将单个分区拆分为多个分区,语法如下:

ALTER TABLE [ IF EXISTS ] name
SPLIT PARTITION partition_name INTO
  (PARTITION partition_name1 { FOR VALUES partition_bound_spec | DEFAULT },
   PARTITION partition_name2 { FOR VALUES partition_bound_spec | DEFAULT } [, ...])

以下命令将分区 sales_south 中区域为“华东”的数据拆分到单独的分区:

ALTER TABLE sales SPLIT partition sales_south INTO
  (
     partition sales_east FOR VALUES IN ('华东'),
     partition sales_south FOR VALUES IN ('中南', '西南')
  );

分区拆分功能支持范围分区和列表分区,但不支持哈希分区,而且只能拆分不包含子分区的简单分区。

拆分出的新分区和其他新分区或者已有分区之间不能存在重叠。如果被拆分的是 DEFAULT 分区,拆分出的新分区必须有一个是 DEFAULT 分区。如果新分区或者已有分区中存在 DEFAULT 分区,其他新分区边界之间可以存在间隔。如果被拆分的分区表不存在 DEFAULT 分区,可以将新分区中的一个设置为 DEFAULT 分区。

如果新分区不包含 DEFAULT 分区,同时分区表也没有 DEFAULT 分区,必须满足以下条件:所有新分区(partition_name1, partition_name2, …)的边界总和等于被拆分的分区边界。新分区中可以存在一个名称和被拆分的分区相同的分区,当我们拆分一个 DEFAULT 分区,并且拆分之后仍然存在 DEFAULT 时就是这种情况。

新分区的创建方法和 CREATE TABLE partition_nameN (LIKE name INCLUDING ALL EXCLUDING INDEXES EXCLUDING IDENTITY) 命令相同,索引和标识列会在完成数据迁移之后创建。新分区将会继承父表的访问方法(access method),如果父表是一个普通表,新分区也是一个普通表;如果父表是一个临时表,新分区也是一个临时表。

分区合并

ALTER TABLE … MERGE PARTITIONS … 命令用于将多个分区合并为单个分区拆分,语法如下:

ALTER TABLE [ IF EXISTS ] name
MERGE PARTITIONS (partition_name1, partition_name2 [, ...])
INTO partition_name;

以下命令将分区 sales_east 和 sales_south 合并为一个分区:

ALTER TABLE sales 
MERGE partitions ( sales_east, sales_south )
INTO sales_south;

分区合并功能支持范围分区和列表分区,但不支持哈希分区,而且只能合并不包含子分区的简单分区。

如果被合并的分区(partition_name1, partition_name2, …)中不包含 DEFAULT 分区:

  • 对于范围分区表,被合并的多个分区边界之间不能存在重叠或者间隔,否则将会返回错误。
  • 对于列表分区表,被合并的多个分区值列表将会组成新分区的值列表。

如果被合并的分区(partition_name1, partition_name2, …)中包含 DEFAULT 分区:

  • 新分区将会成为 DEFAULT 分区。
  • 对于范围分区表和列表分区表,被合并的分区可以包含任何范围或者值列表。

新分区可以与被合并的某一个分区名称相同。

合并分区时,新分区的创建方法和分区拆分时的方法相同。

注意事项

目前的实现中,分区拆分与合并操作都需要获取父表上的 ACCESS EXCLUSIVE 锁,直到完成新分区的创建以及数据迁移。这个限制导致拥有高负载的大型分区表实际上无法执行这些操作。当然,对于其他情况这两个命令还是很方便的。

PostgreSQL 17 刚刚引入了这两个功能,将来的版本肯定会减少锁定的资源,并且支持并行操作,从而变得更加实用。

本站无任何商业行为
个人在线分享 » PostgreSQL 17新特性之分区拆分与合并
E-->