在使用 Easysearch 做统计分析时,很多人都会遇到一个似曾相识的问题:
“我这条聚合写得没问题,但结果总感觉不太对。”
文档数对不上、排行榜顺序异常、同一份数据在不同时间查询结果略有差异……
这些现象往往不是 Bug,而是聚合本身的计算特性在起作用。
本文将从 Easysearch 的聚合机制出发,系统讲清楚聚合精度与近似这一经常被忽略、却非常关键的话题,帮助你在“结果不对”时,知道该从哪里排查。
一、Easysearch 简介:不只是搜索,更是实时分析引擎 #
Easysearch 是由 INFINI Labs 推出的国产自研的分布式搜索与分析引擎,衍生自 Elasticsearch ,广泛应用于:
- 日志分析
- 业务指标统计
- 排行榜与趋势分析
- 实时监控看板
在 Easysearch 中,Aggregations(聚合) 是构建统计报表的核心能力。
但与传统数据库的 GROUP BY 不同,Easysearch 的聚合是分布式、并行、近实时计算的,这也决定了它在“精度”上的一些天然取舍。
二、为什么聚合结果会“看起来不对”? #
在讨论具体问题之前,先明确一个重要前提:
Easysearch 的聚合结果,并不总是“绝对精确”的。
这不是缺陷,而是设计选择。
原因很简单:
- 数据量可能非常大
- 数据分布在多个分片、多个节点
- 聚合需要在有限时间内返回结果
为了在性能、资源、延迟之间取得平衡,Easysearch 在部分场景下会采用近似计算或分阶段合并的方式。
理解这一点,是正确使用聚合的第一步。
三、最常见的精度与近似场景解析 #
下面我们结合实际使用中最容易踩坑的几个聚合场景,逐一拆解“为什么结果会不一样”。
3.1 terms 聚合:排行榜为什么不稳定?
#
terms 是最常用的桶聚合,用于做排行榜、分类统计,例如:
- Top N 用户
- Top N 商品
- Top N 接口
但它也是**最容易产生“精度误解”**的聚合之一。
3.1.1 问题表现 #
- Top 10 排行榜顺序偶尔变化
- 某些边缘值忽隐忽现
- 实际类别很多,但返回结果有限
3.1.2 根本原因 #
terms 聚合的执行过程是:
- 每个分片先统计自己的 Top N
- 再由协调节点进行合并
- 最终返回全局 Top N
为了避免分片返回过多数据,Easysearch 默认会:
- 限制每个分片返回的桶数量 size * 1.5 + 10
- 对低频项进行裁剪
这意味着:分片级别的“候选集”本身就是近似的。
如果想提高精度,可以通过调大 shard_size 来让分片返回更多候选桶。
3.1.3 这是 Bug 吗? #
不是。这是为了避免在高基数场景下,聚合直接拖垮集群。
3.2 文档数量对不上:doc_count 为什么不等于真实行数?
#
很多初学者会用聚合结果去“对账”,例如:
- 按状态聚合后,
doc_count总和 ≠ 索引文档数 - 某些桶的数量明显偏少
3.2.1 常见原因 #
- 查询条件过滤了部分数据
- 时间范围与字段值不一致
- 嵌套字段未使用
nested聚合 - 刷新(refresh)尚未发生
其中,第 3 点尤其常见。
如果字段是 nested 类型,却使用了普通聚合方式:
- Easysearch 统计的是“父文档”
- 而不是嵌套对象本身
结果自然会“看起来不对”。
3.3 Cardinality(去重统计):为什么永远不是精确值? #
cardinality 聚合用于统计去重后的数量,例如:
- UV(独立用户数)
- 去重 IP 数
它的特点只有一个:快,但不保证绝对精确
3.3.1 为什么? #
因为 cardinality 使用的是概率算法(如 HyperLogLog):
- 内存占用固定
- 计算速度快
- 允许极小误差,默认误差率通常在 5% 左右(取决于配置)
这种设计非常适合趋势分析,但并不适合财务级别对账。
如果你发现:
- 不同时间查询结果略有波动
- 与数据库精确统计存在小差异
这通常是正常现象。
如果您想提高去重计数的准确度,可以调高
precision_threshold参数。该参数允许在增加内存消耗的前提下,提升基数估算的精度。当唯一值数量不超过precision_threshold时,Easysearch 可提供高度精确的近似结果;该参数最大可设置为约 40000,超过此数值的去重计数将转为估算,精度会有所下降。
3.4 浮点数聚合:avg / sum 为什么有小数误差?
#
在做金额、时长等指标统计时,有些人会注意到:
avg结果出现非常长的小数- 累加结果存在微小误差
这是浮点数计算的固有特性,并非 Easysearch 特有问题。
在分布式环境中:
- 多分片分别计算
- 多次合并中存在舍入误差
这类误差通常在业务可接受范围内。
四、如何判断“不对”到底是不是问题? #
一个非常实用的判断原则是:
先区分“统计口径不一致”和“计算误差”
可以从以下几个维度自查:
- 是否使用了正确的字段类型
- 是否涉及嵌套对象
- 是否使用了近似聚合(如
cardinality) - 是否存在时间窗口、刷新延迟
- 是否把 Easysearch 当成了“强一致数据库”
- Deleted Documents(已删除文档):在分片合并(Segment Merge)之前,已删除的文档仍然占用存储,且在某些底层的计数逻辑中可能产生微小干扰(虽然聚合通常会过滤掉它们,但在极高并发更新场景下会有瞬间差异)。
如果这些都明确了,80% 的“看起来不对”都会变得合理。
五、什么时候应该追求“绝对精确”? #
Easysearch 非常适合:
- 运营分析
- 趋势判断
- 实时监控
- 排行榜展示
但并不适合:
- 财务结算
- 强一致对账
- 精确计费系统
一个常见的实践是:用 Easysearch 做分析,用数据库做结算, 各司其职,反而更稳定。
六、小结:理解近似,才能用好聚合 #
聚合结果“看起来不对”,往往不是写法错误,而是:
- 没理解分布式计算的取舍
- 没意识到近似算法的存在
- 把分析引擎当成了事务系统
只要记住一句话:
Easysearch 聚合追求的是“可用、快速、趋势可信”,而不是“逐条精确”
你就能在使用聚合时,既放心,又不纠结。





