Elasticsearch-80-海量bucket的优化机制

概述

先来看一个需求

现在有一堆数据,是每个演员的每个电影的评论,现在我们要取到10个演员的评论数量排名前5的电影

看一下请求体

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
"aggs" : {
"actors" : {
"terms" : {
"field" : "actors",
"size" : 10,
"collect_mode" : "breadth_first"
},
"aggs" : {
"costars" : {
"terms" : {
"field" : "films",
"size" : 5
}
}
}
}
}
}

第一个聚合,根据演员分组,就能拿到每个演员的评论的数量, 然后 size是10 取前10个,collect_mode先不管,然后是第二个按电影分组,拿到了每个演员每个电影的评论数量,取前5的电影,这个需求就ok了

接下来看一下深度优先和广度优先的两种聚合方式

深度优先的聚合方式

假设每个演员对应的电影数据如下

1
2
    actor1               actor2            .... actor
film1 film2 film3 film1 film2 film3 ...film

比如说,现在有10万个actor,其实最后只需要10个就好了

但是我们使用的是深度优先的方式,它已经构建了一颗完整的树出来了,假设每个actor有10个电影, 那就是10万actor + 100万film的数据量的树.

最后再裁剪掉10万个actor中的99990个actor和99990 10 个film,剩下10个actor, 每个actor再裁剪掉5个film,剩下的数据就是10 5 = 50个, 从110万的数据裁剪成5个.

先构建了大量的数据,最后裁掉99.99%的数据,浪费了

广度优先的方式执行

先构建actor的数,如下

1
actor1    actor2    actor3    ..... n个actor

假设10万个actor,但是现在不去构建他下面的film数据, 数据量也就是10万个,然后裁掉99990个 剩下10个,这个时候再去构建film,裁剪掉5个

数据就是从10万到剩下的50个,比上面的深度优先性能高了10倍.

再看上面那个请求体,其中collect_mode参数值为breadth_first,就是表示广度优先