ES高基数聚合优化测试报告

363 阅读2分钟

一、背景:

  产品上想要对资产进行聚合,资产的定义是ip+port,在es里是两个字段,目前对着两个字段进行cardinality聚合在客户那直接报(57亿)超时

二、解决方案

  将ip+port单独写为一个字段,但是如果对这个字段进行聚合,发现时间还是比较长,因为基数比较大,在这种高基数聚合下,需要参与 hash 运算的数据集合过于庞大。

  解决思路:

    1、对于字段值,存储Hash值(写入时处理)

    2、基于Hash 做聚合和统计分析操作

  刚好es7.x之后可以借助mapper-murmur3 插件实现Hash 值类型

PS:

高基数:意味着一个字段包含很大比例的唯一值。

低基数:意味着一个字段包含很多重复的值。

三、测试:

测试1

配置:64g内存 数据磁盘716g Intel(R) Xeon(R) CPU E5-2609 v4 @ 1.70GHz 逻辑cpu数量-8

es:版本-7.16.2 堆内存大小-16g

数据量: 5521711 条数据

1.png

将ip port存成一个字段,进行聚合,需要近17s:

2.png

由于这个字段是高基数聚合,所以采用提前hash的方式优化,直接聚合hash后的结果只需要近600ms

3.png

测试2

配置:64g内存 数据磁盘1.6t Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz 逻辑cpu数量-48

es:版本-7.17.3 堆内存大小-16g

数据量: 14531707 条数据

将ip port存成一个字段,进行聚合,需要3.67s:

4.png

对hash值进行聚合结果:

5.png

测试3

配置:同测试2

索引: 同测试2
数据量: 39568036 条数据

对ip_port进行聚合,需要12.86s:

6.png

对ip_port.hash进行聚合,需要583ms:

7.png

四、结论:

在pre hash之后,可以看到聚合速度有了很大提升,并且hash后的聚合时间并不是线性增长的,可以预估57亿的数据聚合耗时应该小于1.4分钟,客户的es配置为内存128G,硬盘24T,32核,理论上性能会更好

五、思考:

虽说pre hash大大提高了聚合的性能,但还是有量变而导致质变的问题,这种方法也只能作为阶段性方案。所以感觉限制数据的统计量,从产品层面去做出某些“妥协”,可能才是最终的解决之道。