首页/数据/NoSQL 速查/AggregatingMergeTree 聚合状态
ClickHouse56 条

AggregatingMergeTree 聚合状态

AggregatingMergeTree 存储聚合函数中间状态(AggregateFunction 列):写入用 -State 组合器,查询用 -Merge 组合器,通常作为物化视图的目标表实现增量预聚合。

NoSQL 速查数据更新于 2026-10-13

它存的是状态而不是结果

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 函数写错或类型不匹配会直接报类型错误,改动列类型时要同步改写入与查询两侧。
聚合状态体积随维度基数增长而膨胀,物化视图的聚合维度要与实际查询模式一致,否则预聚合表可能比明细表还占空间。

易错点

  • State 与 Merge 函数必须成对匹配,写错聚合函数或类型时查询会直接报类型错误
  • 聚合状态随维度基数增长而膨胀,物化视图的分组维度要与查询模式一致
  • 直接 SELECT 状态列得到二进制内容,误当数值使用会得到无意义的结果
  • 物化视图只对写入之后的数据生效,历史数据需要用 INSERT SELECT 回填后才完整

数据来源与参考

  • ClickHouse Docs: AggregatingMergeTree
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌