现象
从oracle同步了2万多数据到es。经过去重统计,数据为1万9千多(也可能多与2万,当时确实是少一点)。原始数据确认无重复。然后把数据从es通过程序导入表格留存,再次人工统计,数据2万。从es查询结果就是少于2万。查询结果和实际结果存在差异。
原因
部分聚合(如 cardinality 基数统计、percentiles 百分位统计)默认使用近似算法(为了性能),结果可能存在误差。
例如 cardinality 聚合通过哈希算法估算唯一值数量,精度可通过 precision_threshold 调整,但会影响性能。
在 Elasticsearch 的 cardinality 聚合中,precision_threshold 参数的取值范围是 1 到 40000,这意味着最大值可以设置为 40000。
关于 precision_threshold 的说明:
作用:该参数定义了一个阈值,当唯一值数量低于这个阈值时,cardinality 聚合会保证结果 100% 精确;当超过这个阈值时,结果会采用近似算法(基于 HyperLogLog++),可能存在误差(通常在 2% 以内)。
最大值限制:ES 内部通过哈希表存储数据,precision_threshold 越大,需要的内存和计算资源越多。官方将最大值限制为 40000,是综合性能与精度后的平衡:
当设置为 40000 时,对于唯一值数量 ≤40000 的场景,结果完全精确;
对于超过 40000 的场景,精度会随数值增大而略有下降,但仍保持较高准确性。
性能影响:设置过高(如接近 40000)会显著增加内存消耗(每个分片可能占用数 MB 内存),并延长聚合计算时间。因此,建议根据实际业务场景调整:
若业务要求绝对精确且唯一值数量较少(如 ≤10000),可设置对应阈值;
若唯一值数量极大(如百万级以上),建议使用默认值(3000)或适当提高(如 10000),在精度和性能间平衡。