elasticsearch Elasticsearch多和聚合
我们在每个索引(~10000)中都有大量文档。但每个文档都非常小,几乎只包含整数值 我们需要对所有的数值场求和elasticsearch Elasticsearch多和聚合,elasticsearch,groovy,nosql,elasticsearch,Groovy,Nosql,我们在每个索引(~10000)中都有大量文档。但每个文档都非常小,几乎只包含整数值 我们需要对所有的数值场求和 第一步-我们要求所有具有映射的可用字段 例如: GET INDEX/TYPE/_mapping GET INDEX/TYPE/_search { // SOME FILTERS TO REDUCE THE NUMBER OF DOCUMENTS "size":0, "aggs":{ "FIELD 1":{ "su
GET INDEX/TYPE/_mapping
GET INDEX/TYPE/_search
{
// SOME FILTERS TO REDUCE THE NUMBER OF DOCUMENTS
"size":0,
"aggs":{
"FIELD 1":{
"sum":{
"field":"FIELD 1"
}
},
"FIELD 2":{
"sum":{
"field":"FIELD 2"
}
},
// ...
"FIELD N":{
"sum":{
"field":"FIELD N"
}
}
}
}
GET INDEX/TYPE/_mapping
GET INDEX/TYPE/_search
{
// SOME FILTERS TO REDUCE THE NUMBER OF DOCUMENTS
"size":0,
"aggs":{
"FIELD 1":{
"sum":{
"field":"FIELD 1"
}
},
"FIELD 2":{
"sum":{
"field":"FIELD 2"
}
},
// ...
"FIELD N":{
"sum":{
"field":"FIELD N"
}
}
}
}
我们的问题是,第二个请求的执行时间与字段N的数量成线性关系
这是不可接受的,因为这仅是总和。因此,我们尝试使用脚本化度量(groovy)生成我们自己的聚合
仅包含两个字段的示例:
// ...
"aggs": {
"test": {
"scripted_metric": {
"init_script": "_agg['t'] = []",
"map_script": "_agg.t.add(doc)",
"combine_script": "res = [:]; res['FIELD 1'] = 0; res['FIELD 2'] = 0; for (t in _agg.t) { res['FIELD 1'] += t.['FIELD 1']; res['FIELD 2'] += t.['FIELD 2']; }; return res",
"reduce_script": "res = [:]; res['FIELD 1'] = 0; res['FIELD 2'] = 0; for (t in _aggs) { res['FIELD 1'] += t.['FIELD 1']; res['FIELD 2'] += t.['FIELD 2']; }; return res"
}
}
}
// ...
但是,我们在脚本中添加的做作越多,执行脚本所需的时间就越长,因此它并不能解决我们的问题
没有太多的例子
您有什么想法可以改进此脚本的性能吗?
或者其他想法?它如何在次线性时间内计算N个和,是否存在这样的系统 1000万份文件实际上并没有那么多。您的查询需要多长时间,您有多少个碎片,CPU的最大值是否为100%?(我本想在评论中问这些问题,但还没有50%的声誉) 如果您对所有字段的总和感兴趣,可以在为文档编制索引时预先计算文档级别的总和,然后在查询时只取这些值的总和
您还可以尝试将字段存储为,看看是否有帮助。您的内存压力和垃圾收集会更小,尽管文档中提到可能会有10-25%的性能损失。脚本通常成本较高。我看不出有什么理由在这里使用脚本。你不能使用总和指标聚合吗?你是什么意思?我们确实在所有字段上使用了总和聚合,它太慢了。为什么要使用脚本,使用这个-我们使用它(看看我的问题:步骤2)。但我们需要在许多文档字段上使用它。不确定这是否有帮助,但我会尝试将第一个请求拆分为多个请求,每个请求聚合一组字段。然后,我将使用批量请求来执行多个请求,您将不得不重复过滤器,尽管可能值得一试。