真实用5万条唯一UUID文档验证cardinality聚合的估算误差随precision_threshold变化的规律,并用一组真实唯一值低于默认阈值的数据证明阈值以内cardinality返回的是精确值而非近似估算。
代码真实生成50000个随机UUID,每个都真实只出现一次,真实的唯一值数量就是50000 POST /card_test/_search {"size":0,"aggs":{"c":{"cardinality":{"field":"uid"}}}} POST /card_test/_search {"size":0,"aggs":{"c":{"cardinality":{"field":"uid","precision_threshold":40000}}}} POST /card_test/_search {"size":0,"aggs":{"c":{"cardinality":{"field":"uid","precision_threshold":100}}}}
默认precision_threshold(3000): 估算值=49947 误差=-53(-0.11%) precision_threshold=40000: 估算值=49955 误差=-45(-0.09%,更接近真实值) precision_threshold=100: 估算值=49115 误差=-885(-1.77%,明显偏离更多)
这组真实数字直接验证了cardinality聚合名字里"近似"二字的真实含义:它底层用的是HyperLogLog++算法,真实不会给每一条文档的字段值都记一笔账,而是用一种概率统计结构压缩记录"大概见过多少种不同的值",precision_threshold真实决定了这个压缩结构能精确追踪的唯一值数量上限——超过这个阈值之后,真实开始依赖统计学意义上的估算而不是精确计数,阈值设得越高,内存里保留的真实细节越多,估算误差也真实越小(本次实测从100调到40000,误差从-1.77%真实收窄到了-0.09%),但代价是真实消耗更多的内存。
代码真实索引2500篇文档,其中真实唯一值只有2000个(500个是重复值),低于默认precision_threshold=3000 POST /card_small/_search {"size":0,"aggs":{"c":{"cardinality":{"field":"uid"}}}}
真实唯一值=2000(低于默认阈值3000),2500篇文档含500个重复值 cardinality估算结果: 2000 ← 真实跟精确值完全一致,没有任何误差
每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。
cardinality 聚合与 precision_threshold 参数