improving-the-performance-of-high-cardinality-terms-aggregations-in-elasticsearch
主要是因为,es里面默认在terms聚合的时候,会创建一个gloalbal ordinals(全局的排序),这种方式对于海量数据的聚合很有效,由于基数总数不大的字段聚合也没有问题。但是对于过滤出来结果很小的数据,字段基数较大的聚合查询非常耗时。 可以通过创建gloalbal ordinals来解决这个问题
"aggregations" : { "top-ibans" : { "terms" : { "field" : "IBAN_keyword" , "execution_hint" : "map"通过设置 "execution_hint": "map" 来避免使用gloalbal ordinals
Global Ordinals
Global Ordinals分布在索引的所有段segment中,所以如果新增或删除一个分段时,需要对全局序号进行重建。 重建需要读取每个分段的每个唯一项,基数越高(即存在更多的唯一项)这个过程会越长。Global Ordinals是构建在内存 fielddata 和 doc values 之上的。实际上,它们正是 doc values 性能表现不错的一个主要原因。
Ordinals的构建只被应用于字符串。数值信息(integers(整数)、geopoints(地理经纬度)、dates(日期)等等)不需要使用Ordinals映射,因为这些值自己本质上就是Ordinals映射。
Global Ordinals在遇到High Cardinality(Large Number of Unique Values,即某个字段的值有很多很多种,可以理解为count distinct这个字段的数值大小)的情况下,聚合效率低。
execution_hint设置
map:为了在每个桶中聚合数据,直接使用field values,当只有很少文档能够匹配查询的时候使用(返回结果集合比较小的时候适用)
global_ordinals:使用field的ordinals,预先为每个ordinal value分配一个桶,默认用于top-level terms aggregations,不适合于多个嵌套aggregations
global_ordinals_hash:使用field的ordinals,动态为每个ordinal value分配一个桶,默认用于inner aggregations
global_ordinals_low_cardinality:通过使用每个segment ordinals来计算count,使用global ordinals来重新map这些count到global counts,应用于leaf terms aggregations,内存开销和字段非重复值的个数线性相关,默认用于low-cardinality fields 字段的值种类很少的情况
es官网给出的解决方案 www.elastic.co/cn/blog/imp…