它存的是状态而不是结果
AggregatingMergeTree 把聚合函数的中间状态存进表里:列类型写成 AggregateFunction(函数, 参数类型),写入用带 State 后缀的函数(uniqState、avgState),查询用带 Merge 后缀的函数(uniqMerge、avgMerge)把状态合并成最终结果。状态可以跨多个 part 继续合并,所以它天然适合做增量预聚合。
最常见的用法是当物化视图目标表
典型组合是物化视图把明细表的写入按维度聚合后落进 AggregatingMergeTree 表,查询直接读这张表并做 Merge。这样既能承载不可加指标(去重计数、平均、分位数),也不需要每次重算全量明细;代价是聚合状态的体积会随维度基数增长而膨胀。
基本信息
| 列类型 | AggregateFunction(func, types...),如 AggregateFunction(uniq, UInt64) |
|---|---|
| 写入函数 | uniqState(x)、avgState(x) 等带 State 后缀 |
| 查询函数 | uniqMerge(col)、avgMerge(col) 等带 Merge 后缀 |
| 常见搭配 | 物化视图加 AggregatingMergeTree 目标表 |
| 硬限制 | 状态列不能直接读取,必须用对应 Merge 函数 |
示例
示例
CREATE TABLE agg_daily
(
d Date,
n UInt64,
u AggregateFunction(uniq, UInt64),
a AggregateFunction(avg, Float64)
)
ENGINE = AggregatingMergeTree
ORDER BY (d, n);
-- 写入聚合状态
INSERT INTO agg_daily
SELECT d, n, uniqState(id), avgState(v)
FROM events GROUP BY d, n;
-- 查询时合并状态得到结果
SELECT d, n, uniqMerge(u) AS uv, avgMerge(a) AS avg_v
FROM agg_daily GROUP BY d, n;典型使用场景
- 增量预聚合:把明细预聚合成天或小时维度,查询直接读聚合表
- 不可加指标:去重计数、平均、分位数这类必须保留状态才能算对的指标
- 多级汇总:小时状态可以继续合并成天与月,不必回退到明细
- 实时落库:物化视图让新写入的明细自动聚合并落盘
- 口径验证:用同一批数据对比明细计算与状态合并的结果
各环节写法
| 环节 | 写法 | 注意 |
|---|---|---|
| 建表 | AggregateFunction(函数, 类型) | 函数与类型必须与写入时一致 |
| 写入 | uniqState、avgState 等 | 聚合维度要与查询维度对齐 |
| 查询 | uniqMerge、avgMerge 等 | 直接查询状态列得到的是二进制 |
| 合并 | 由后台合并自动完成 | 状态可以跨 part 继续合并 |
状态列直接查询出来是二进制内容,必须用对应的 Merge 函数读取;State 与 Merge 函数写错或类型不匹配会直接报类型错误,改动列类型时要同步改写入与查询两侧。
聚合状态体积随维度基数增长而膨胀,物化视图的聚合维度要与实际查询模式一致,否则预聚合表可能比明细表还占空间。