将另一个数据库的分区添加到 Postgres 12 中的现有分区 table

Adding a partition from another DB to existing partitioned table in Postgres 12

问题的简短描述

我需要构建一个分区 table“用户”,其中 2 个分区位于不同的服务器(莫斯科和汉堡),每个分区 table 列:
id - 自动递增的整数主键
region - smallint 分区键,汉堡为 100,莫斯科为 200
login - 长度为 100 的唯一字符。

我打算将 id 的序列作为汉堡的 n*1000 + 100 和莫斯科的 n*1000 + 200,所以只需查看主键我就会知道它属于哪个分区。

region 旨在只读且创建后永不更改,因此不会在分区之间移动任何记录。

SELECT 查询必须能够 return 来自所有分区的记录并且 UPDATE 查询必须能够修改所有分区上的记录,INSERT/DELETE 查询必须能够 add/delete 只记录到本地分区,因此存储在其中的数据不是完全隔离的。

做了什么

使用 pgAdmin4

  1. 我在汉堡服务器上创建了一个“测试”table,添加了所有列信息,将其标记为已分区 table,分区键 region 和分区类型 List .
  2. 我在此 table 中创建了一个“汉堡”分区,将主键约束添加为 idregion 并将唯一键约束添加为 loginregion.
  3. 我在莫斯科服务器上创建了一个“moscow”table,其列信息与“test”相同
  4. 我向汉堡服务器添加了 postgres_fdw 扩展,创建了指向莫斯科服务器和用户映射上的数据库的外国服务器。
  5. 我在汉堡服务器上添加了“moscow”外国 table 指向莫斯科服务器上的“moscow”table。

我的问题是什么

我不知道如何将这个外部 table 作为第二个分区附加到“测试”table。

当我试图通过“测试”table 分区属性中的 pgAdmin 对话框 attach 分区时,它向我显示了一个错误:cannot unpack non-iterable Response object

当我尝试使用查询添加分区时:

ALTER TABLE public.test ATTACH PARTITION public.moscow FOR VALUES IN (200);

显示错误:

ERROR:  cannot attach foreign table "moscow" as partition of partitioned table "test"
DETAIL:  Table "test" contains unique indexes.
SQL state: 42809

我从 login 列中删除了唯一约束,但它显示相同的错误。

当我使用相同的属性对 table 进行分区并且最初位于同一台服务器上的两个分区都运行良好时,除了 postgres 监视 login 每个分区的唯一性而不是整个 table,但我认为这是它的局限性。

那么,如何将位于第二台服务器上的 table 作为分区附加到位于第一台服务器上的分区 table?

错误信息很清楚:因为你不能在分区table上创建索引,PostgreSQL 不能创建唯一索引的分区。但是需要唯一索引来实现约束。

查看此来源评论:

/*
 * If we're attaching a foreign table, we must fail if any of the indexes
 * is a constraint index; otherwise, there's nothing to do here.  Do this
 * before starting work, to avoid wasting the effort of building a few
 * non-unique indexes before coming across a unique one.
 */

要么放弃唯一约束,要么不使用外部 table 作为分区。

好的,我终于可以添加一个外部 table 作为分区到分区 table。

  1. 有必要在 id 上删除 primary key 属性,在 login 列上删除 unique 属性分区 table
  2. 之后我能够将外部 table 作为分区附加到分区 table
  3. 后来我在 id 上添加了 primary key 属性,在每个 login 列上添加了 unique 属性本地分区.

所以最后我得到了唯一的全局 id,因为它是由每个数据库的序列生成的,值从不相交。对于 login 唯一性,我必须在插入之前手动检查全局 table 是否有任何记录。

P.S。希望 postgres 中的这种分区机制适用于地理上遥远的区域。