分区表支持任意列作为主键

在PostgreSQL中,分区表的主键只能建立在分区键上,且不能作为外键引用。PolarDB PostgreSQL版支持分区表使用任意列作为主键或者外键引用。

前提条件

支持的PolarDB PostgreSQL版的版本如下:

PostgreSQL 14(内核小版本14.10.17.0及以上)

说明

您可通过如下语句查看PolarDB PostgreSQL版的内核小版本的版本号:

select version();

参数说明

polar_pk_in_non_partition_column_mode:用于指定非分区键上的主键所使用的索引类型,取值如下:

  • none/local_pk:不支持主键建立在非分区键上,否则会提示错误。

  • global_index:在非分区键上创建主键时,会使用全局索引作为约束。

使用限制

  • 指定的主键如果包含所有分区键,则默认使用局部索引作为主键,否则使用全局索引作为主键。

  • 指定的约束如果包含所有分区键,则默认使用局部索引作为唯一约束,否则使用全局索引作为唯一约束。

  • 分区表的添加主键语法只能使用全局索引,因为局部索引不一定能满足约束,添加唯一约束语法也是如此。

  • 分区表被外键引用的行不允许发生跨分区更新,因为跨分区更新本质上是一次删除和一次插入,在执行删除时会检测此行是否被外键引用。

示例

设置polar_pk_in_non_partition_column_modenone,并在非分区键上创建主键。

SET polar_pk_in_non_partition_column_mode = none;
CREATE TABLE pt1 (a int, b int primary key, c varchar) PARTITION BY RANGE(a);
ERROR:  unique constraint on partitioned table must include all partitioning columns
DETAIL:  PRIMARY KEY constraint on table "pt1" lacks column "a" which is part of the partition key.

设置polar_pk_in_non_partition_column_modeglobal_index,并在非分区键上创建主键。

SET polar_pk_in_non_partition_column_mode = global_index;
CREATE TABLE pt1 (a int, b int primary key, c varchar) PARTITION BY RANGE(a);
CREATE TABLE pt1_p1 PARTITION OF pt1 FOR VALUES FROM (0) TO (1);
\d pt1
               Partitioned table "public.pt1"
 Column |       Type        | Collation | Nullable | Default
--------+-------------------+-----------+----------+---------
 a      | integer           |           |          |
 b      | integer           |           | not null |
 c      | character varying |           |          |
Partition key: RANGE (a)
Indexes:
    "pt1_pkey" PRIMARY KEY, btree (b) GLOBAL
Number of partitions: 1 (Use \d+ to list them.)

如果分区表的主键包含了所有分区键,则使用局部索引作为主键,无论参数polar_pk_in_non_partition_column_mode的取值是什么,此为PostgreSQL的默认行为。

CREATE TABLE pt2 (a int primary key, b int, c varchar) PARTITION BY RANGE(a);
CREATE TABLE pt2_p1 PARTITION OF pt2 FOR VALUES FROM (0) TO (1);
\d pt2
               Partitioned table "public.pt2"
 Column |       Type        | Collation | Nullable | Default
--------+-------------------+-----------+----------+---------
 a      | integer           |           | not null |
 b      | integer           |           |          |
 c      | character varying |           |          |
Partition key: RANGE (a)
Indexes:
    "pt2_pkey" PRIMARY KEY, btree (a)
Number of partitions: 1 (Use \d+ to list them.)

如果必须使用全局索引作为主键,可以使用修改表主键的语法。

ALTER TABLE pt2 DROP CONSTRAINT pt2_pkey;
CREATE UNIQUE INDEX pt2_pkey ON pt2 (a) GLOBAL;
ALTER TABLE pt2 ADD PRIMARY KEY USING INDEX pt2_pkey;
\d pt2
               Partitioned table "public.pt2"
 Column |       Type        | Collation | Nullable | Default
--------+-------------------+-----------+----------+---------
 a      | integer           |           | not null |
 b      | integer           |           |          |
 c      | character varying |           |          |
Partition key: RANGE (a)
Indexes:
    "pt2_pkey" PRIMARY KEY, btree (a) GLOBAL
Number of partitions: 1 (Use \d+ to list them.)