reference table适合小而静态、高频关联的维度表,如countries;co-location要求多表分布列兼容、分片数一致,以实现本地join。二者协同可避免跨节点join,提升查询性能。

Citus 中的 reference table(引用表)和分布式表的 co-location(共置)是影响查询性能与数据一致性的两个关键设计点。合理使用 reference table 可避免跨节点 JOIN,而正确配置 co-location 能让分布式 JOIN 变成本地 JOIN,大幅降低网络开销和延迟。
Reference table 适合什么场景
Reference table 是在每个分片节点(worker node)上都完整复制一份的表,通常用于小而静态、高频关联的维度表,比如 countries、currencies、status_codes 等。
- 适用于大小通常在几 MB 以内,且更新频率极低(如每月或更少)的表
- JOIN 时无需指定分布列,Citus 自动将查询下推到各 worker,用本地副本完成关联
- 写操作(INSERT/UPDATE/DELETE)会广播到所有节点,因此不适用于高写入负载的表
- 创建方式:
SELECT create_reference_table('table_name');
Co-location 是如何工作的
Co-location 指多个分布式表使用相同的分布列(distribution column)、相同的分片数量(shard count)和相同的分布方法(hash 或 range),从而保证相同分布键值的数据落在同一分片上。这样,基于该键的 JOIN 就能在单个 worker 上完成,无需跨节点 shuffle。
- 必须确保所有参与 co-located JOIN 的表:分布列名可不同,但数据类型和值域需兼容
- 分片数必须一致(可通过
alter_distributed_table调整,但需注意重分布成本) - 若某表未 co-located,Citus 会退化为 broadcast JOIN 或 repartition JOIN,性能明显下降
- 检查 co-location 组:
SELECT * FROM citus_shards WHERE table_name = 't1';对比colocation_id
Reference table 和 co-location 的协同使用
两者不是互斥关系,而是互补策略。例如:一个订单事实表(orders)按 tenant_id 分布,与租户维度表(tenants)co-located;同时,币种表(currencies)作为 reference table,被 orders 直接 JOIN 使用。
- JOIN tenants → 利用 co-location 实现本地 hash join
- JOIN currencies → 利用 reference table 实现无条件本地 lookup
- 避免把 currencies 设为分布式表再强行 co-locate —— 冗余分片 + 额外广播开销
- 若某张表既需要被高频 JOIN,又偶尔按非分布列查询,可考虑加 partial index 或物化视图,而非牺牲 co-location
常见误用与排查建议
性能问题常源于隐式破坏 co-location 或误判 reference table 适用性。
- ALTER TABLE 修改分布列后未重新设置 co-location,导致
citus_shards.colocation_id不一致 - 将中等大小(如 50MB+)的表设为 reference table,引发 worker 启动慢、备份膨胀、DDL 延迟
- JOIN 时用了函数包装分布列(如
lower(user_id)),导致 Citus 无法识别分布键匹配,降级为 repartition - 用
EXPLAIN查看执行计划:出现Remote Subquery或Repartition即提示 co-location 失效;出现Local Join或Reference Table Join表示优化生效










