在 Doris中,如何通过配置 Colocate Group 实现本地化计算、零网络传输的极速关联查询?
在 Apache Doris 中,Colocate Join 是一种极速关联查询技术。它通过将相互关联的表(如事实表和维度表,或主表和子表)的数据按相同的分桶键和路由规则,强制存储在相同的物理节点(BE)上。
当进行 Join 查询时,Doris 可以直接在本地进行数据关联,彻底避免了节点间的数据 Shuffle(网络传输),从而实现百毫秒甚至毫秒级的极速关联查询。
以下是实现 Colocate Group 的完整配置步骤、原理及验证方法。
一、 Colocate Group 的核心约束(前提条件)
要让多张表加入同一个 Colocate Group,它们必须满足以下强一致性约束:
- 分桶键(Distribution Keys)一致:分桶列的数量、类型和顺序必须完全一致。
- 分桶数(Bucket Number)一致:表的分桶数量必须完全相同。
- 副本数(Replication Number)一致:表的副本数量必须相同。
- 同数据库:属于同一个 Database(跨库的 Colocate 暂不支持)。
二、 实战:配置 Colocate Group
假设我们有两张表:订单表 orders 和订单详情表 order_items,它们通过 order_id 进行关联。
1. 创建订单表(主表)
在 PROPERTIES 中通过 "colocate_with" = "group_order_details" 属性来定义/加入一个 Colocate Group。
CREATE TABLE orders (
order_id BIGINT NOT NULL COMMENT "订单ID",
user_id BIGINT NOT NULL COMMENT "用户ID",
order_date DATE COMMENT "下单日期",
total_amount DECIMAL(15, 2) COMMENT "总金额"
) ENGINE=OLAP
DUPLICATE KEY(order_id)
DISTRIBUTED BY HASH(order_id) BUCKETS 16 -- 1. 分桶键为 order_id,分桶数为 16
PROPERTIES (
"colocate_with" = "group_order_details", -- 2. 定义 Colocate Group 组名
"replication_num" = "3" -- 3. 副本数为 3
);
2. 创建订单详情表(子表)
详情表必须保持相同的分桶键、分桶数、副本数,并指向相同的 colocate_with 组名。
CREATE TABLE order_items (
item_id BIGINT NOT NULL COMMENT "明细ID",
order_id BIGINT NOT NULL COMMENT "订单ID", -- 必须与 orders.order_id 类型一致
product_id BIGINT NOT NULL COMMENT "商品ID",
price DECIMAL(15, 2) COMMENT "单价",
quantity INT COMMENT "数量"
) ENGINE=OLAP
DUPLICATE KEY(item_id)
DISTRIBUTED BY HASH(order_id) BUCKETS 16 -- 1. 分桶键必须也是 order_id,分桶数必须是 16
PROPERTIES (
"colocate_with" = "group_order_details", -- 2. 组名必须完全一致
"replication_num" = "3" -- 3. 副本数必须一致
);
三、 验证 Colocate 效果
配置完成后,我们需要验证数据是否真的实现了本地化计算。
1. 验证元数据状态
使用以下命令查看 Colocate Group 的状态:
SHOW COLOCATE JOIN;
输出关键字段解读:
- GroupId:组 ID(格式通常为
db_id.group_id)。 - GroupName:组名(如
group_order_details)。 - TableIds:该组内包含的表 ID。
- IsStable:必须为
true。如果是false,说明 Doris 正在后台进行数据重平衡(Rebalance)以强制对齐,此时查询可能仍会有 Shuffle。
2. 验证执行计划(EXPLAIN)
运行你的 Join 查询,并在前面加上 EXPLAIN:
EXPLAIN
SELECT *
FROM orders o
JOIN order_items i ON o.order_id = i.order_id;
如何判断成功?
在输出的执行计划(Execution Plan)中,观察 HASH JOIN 节点:
- 如果看到
colocate: true或者没有HASH_SHUFFLE/BROADCAST相关的 Exchange 节点,说明 Colocate Join 成功触发。 - 数据直接在本地的 BE 节点上进行 Scan 和 Join,无任何跨节点数据传输。
四、 进阶:Colocate 组的维护与行为
自动负载均衡(Rebalance):
当 BE 节点宕机、扩容、或缩容时,Doris 的 FE(Frontend)会自动调度,重新将同一个 Colocate Group 内的所有表的分片(Tablets)搬迁到相同的 BE 节点上,这个过程是自动的,但重建期间IsStable会临时变为false。如何退出 Group:
如果不想让某张表继续在组内,可以通过ALTER TABLE修改属性(将其设置为空):sqlALTER TABLE order_items SET ("colocate_with" = "");动态分区表的 Colocate:
如果表使用了动态分区,只要分桶规则和副本数一致,依然可以使用 Colocate Group。Doris 会确保所有分区的数据都按规则对齐。
五、 极速性能调优建议
- 分桶键的选择:分桶键不仅是 Join 的关联键,也决定了数据的分布。选择高基数(Cardinality)的列作为分桶键(如本例中的
order_id),避免严重的数据倾斜。 - 合理设置 Bucket 数量:
- 建议单个 Bucket 的数据量在 1GB ~ 10GB 之间。
- 分桶数不宜过多,否则会增加 FE 元数据压力和 BE 的线程开销。
- 避免过度使用:只对高频、大表关联、对延迟极其敏感的场景使用 Colocate Group。因为强行绑定多张表的数据分布会降低 HDFS/对象存储/本地磁盘的写入并发灵活性。