合并时求和是怎么工作的
SummingMergeTree 在后台合并 part 时,把排序键相同的行合并成一行,其中的数值列自动求和。写入侧仍然按明细行写,查询侧读到的通常已经是聚合后的结果,数据量随合并逐步收敛,起到轻量预聚合的作用。
它不是精确的预聚合
求和发生在合并阶段而不是写入阶段,合并时机由后台决定,所以查询可能读到尚未合并的重复键行。可靠用法是查询时再加一层 sum 加 group by,或者接受最终一致。另外它只适合可加性指标:平均值这类不可加指标要存分子与分母,或者改用 AggregatingMergeTree 保存聚合状态。
基本信息
| 引擎参数 | SummingMergeTree([columns]),不指定时对所有非排序键数值列求和 |
|---|---|
| 合并语义 | 按排序键聚合,非求和列取任意一行值 |
| 读取兜底 | 未合并数据仍有重复键,查询需 SUM 加 GROUP BY 或 FINAL |
| 适用指标 | 计数、金额等可加性指标 |
| 适用版本 | ClickHouse 各主流版本均支持 |
示例
示例
CREATE TABLE daily_sales
(
d Date,
shop_id UInt64,
orders UInt64,
amount Decimal(18, 2)
)
ENGINE = SummingMergeTree((orders, amount))
ORDER BY (d, shop_id);
INSERT INTO daily_sales VALUES (today(), 1, 1, 9.9), (today(), 1, 2, 19.8);
-- 查询时统一带上聚合,未合并的行也能得到正确结果
SELECT d, shop_id, sum(orders), sum(amount)
FROM daily_sales
GROUP BY d, shop_id;典型使用场景
- 明细直写:上游按事件写入,预聚合在合并阶段自动完成
- 计数与金额汇总:按天、按门店统计可加指标
- 降低存储:重复维度行的数值被合并,长期看行数明显减少
- 实时看板:查询侧再加 sum 兜底,兼顾实时性与最终一致性
- 结构迁移:从明细表切换到预聚合表时保持同一套查询写法
要素与注意
| 要素 | 含义 | 注意 |
|---|---|---|
| 排序键 | 合并的聚合维度 | 应选低频、稳定的维度列 |
| 求和列 | 参与求和的数值列 | 不写时对所有非排序键数值列求和 |
| 非求和列 | 合并时取任意一行值 | 不要依赖其取值做业务判断 |
| FINAL | 查询时强制合并 | 代价高,仅用于临时核对 |
它不维护中间聚合状态,适合可加性指标;平均值这类不可加指标应先存分子与分母,或者改用 AggregatingMergeTree 保存聚合状态再合并。
排序键里出现高基数列会让合并几乎无收益,因为每个键值都只有一行;键要选真正的聚合维度,行数才会收敛下来。