Citus 11.1中带外键的分布式表创建失败问题排查
Citus 11.1分布式表创建失败原因分析
我计划从Citus 11.0迁移至11.1,使用官方GitHub提供的docker-compose文件。以下脚本在Citus 11.0中可正常运行,但在11.1中执行失败:
create table tmp_table1 ( id varchar(36) not null, tenant_key varchar(36) not null, value varchar(255), primary key (tenant_key, id) ); create table tmp_table2 ( id varchar(36) not null, tenant_key varchar(36) not null, value varchar(255), primary key (tenant_key, id) ); alter table tmp_table2 add constraint fkxxx foreign key (tenant_key, id) references tmp_table1; SELECT create_distributed_table('tmp_table1', 'tenant_key'); SELECT create_distributed_table('tmp_table2', 'tenant_key', colocate_with => 'tmp_table1');
执行最后一行SELECT create_distributed_table('tmp_table2', 'tenant_key', colocate_with => 'tmp_table1');时出现如下错误:
ERROR: complex joins are only supported when all distributed tables are co-located and joined on their distribution columns CONTEXT: SQL statement "SELECT fk."tenant_key", fk."id" FROM ONLY "public"."tmp_table2" fk LEFT OUTER JOIN ONLY "public"."tmp_table1" pk ON ( pk."tenant_key"::pg_catalog.text OPERATOR(pg_catalog.=) fk."tenant_key"::pg_catalog.text AND pk."id"::pg_catalog.text OPERATOR(pg_catalog.=) fk."id"::pg_catalog.text) WHERE pk."tenant_key" IS NULL AND (fk."tenant_key" IS NOT NULL AND fk."id" IS NOT NULL)
失败原因
Citus 11.1对外键约束的验证逻辑做了强化。具体原因如下:
- 你的外键
fkxxx基于tmp_table2的(tenant_key, id)关联tmp_table1的主键(tenant_key, id) - 虽然两个表都指定按
tenant_key做同组 colocating,但Citus 11.1在将tmp_table2转为分布式表时,会触发外键合法性验证:此时tmp_table1已经是分布式表,而外键关联同时用到了非分布列id,属于复杂join场景,新版本的验证逻辑要求这类join必须严格匹配分布列关联规则,因此抛出错误 - Citus 11.0没有这个严格的前置验证,所以可以正常执行
解决办法
调整操作顺序,先完成分布式表的创建与同组配置,再添加外键约束:
-- 1. 创建普通表 create table tmp_table1 ( id varchar(36) not null, tenant_key varchar(36) not null, value varchar(255), primary key (tenant_key, id) ); create table tmp_table2 ( id varchar(36) not null, tenant_key varchar(36) not null, value varchar(255), primary key (tenant_key, id) ); -- 2. 将表转为分布式表并配置同组 SELECT create_distributed_table('tmp_table1', 'tenant_key'); SELECT create_distributed_table('tmp_table2', 'tenant_key', colocate_with => 'tmp_table1'); -- 3. 最后添加外键约束 alter table tmp_table2 add constraint fkxxx foreign key (tenant_key, id) references tmp_table1;
当两个表已经是同组分布状态时,Citus可以确认外键关联的行必然存储在同一个分片上,因此会通过外键验证。
内容的提问来源于stack exchange,提问作者Alexis Hassler
相关产品推荐
相关产品推荐

