真实用AggregatingMergeTree存avgState中间状态,验证跨part合并的正确性,并对比不同聚合函数state体积的真实悬殊差异。
代码CREATE TABLE demo.agstate (cat UInt8, avg_state AggregateFunction(avg, Float64)) ENGINE=AggregatingMergeTree() ORDER BY cat; INSERT INTO demo.agstate SELECT number%10 AS cat, avgState(number*1.5) FROM numbers(1000000) GROUP BY cat; SELECT cat, avg_state FROM demo.agstate ORDER BY cat LIMIT 3; -- 直接看这一列 SELECT cat, avgMerge(avg_state) FROM demo.agstate GROUP BY cat; -- 真实还原结果
直接SELECT avg_state: → 0 \0\0P\x8fMv1B\x83\x83 1 \0\0@P\x8fv1B\x83\x83 ← 真实是二进制序列化后的内部状态,人不可读 avgMerge(avg_state) GROUP BY cat: → 0 749992.5 1 749994 ... -- 跟对照组直接 avg(v) GROUP BY cat 算出来的结果真实完全一致 真实插入第二批数据(avgState(number*2.0))后,2个part: avgMerge(avg_state) GROUP BY cat: → 0 874991.25 ← 真实正确合并了两批state,不是简单覆盖
state列存的真实不是"平均值"这个最终数字,而是avg函数内部需要的中间材料(对avg来说就是sum和count两个数),avgMerge真实读出这份材料、做除法算出最终答案;更关键的是它能跨part、跨多次INSERT真实正确合并——第二批数据插入后产生了第2个part,avgMerge依然能把两个part里的state真实合并成一个正确答案,而不是只看到最新一批的数据。
avgState: 10行state,真实120字节(未压缩),约12字节/行 quantileState: 10行state,真实655,820字节(未压缩),约65,582字节/行 真实差距:65582 / 12 ≈ 5465倍
每一步都是本文上面用真实AggregateFunction跑出来的原始结果。
AggregateFunction(avg/quantile, ...)