愚者求师之过,智者从师之长。

【求解】实时聚合查询 并发 响应指数上升??

Elasticsearch | 作者 IFT8 | 发布于2016年12月16日 | 阅读数:3512

http://elasticsearch.cn/question/654
同样2kw数据,同样,并发上去响应就指数型上升,200ms>40s!!!
cpu load 40% io 20% 求解瓶颈在哪里?
8节点,16分片,1备份,单个分片10G 左右,索引300G
{
  "size": 0,
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "created_at": {
              "from": "2016-12-08","to": "2016-12-13"
            }
          }
        },
        {
          "terms": {
            "state": [
              2,
              3,
              4
            ]
          }
        }
      ]
    },
    "aggregations": {
      "aggs": {
        "terms": {
          "field": "c_type",
          "size": 2147483647
        },
        "aggregations": {
          "aggs": {
            "terms": {              "field": "c_id",
              "size": 2147483647
            },
            "aggregations": {
              "aggs": {
                "terms": {
                  "field": "state",
                  "size": 2147483647
                }
              }
            }
          }
        }
      }
    }
  }
}
 
已邀请:

kennywu76 - Wood^Trip.com

赞同来自: IFT8

不清楚你这个c_type和c_id以及state的cardinality (uniq值)有多高, 从你aggregation里给的size来看,似乎是很高的,所以设置这么大的size是想返回所有的值。
 
如果这几个字段的cardinality非常高的话,这个3层嵌套的terms聚合开销是非常高的。一方面这个聚合计算需要生成的bucket随着cardinality的增加而指数级增加,对于heap内存的消耗非常巨大,并发量高的情况下,生成的垃圾应该非常多,JVM GC频率应该显著增加,对CPU消耗比较高。  另外一方面结果集应该也是非常巨大的,因为你划分了16个shard,计算过程中,每个shard都需要返回3个bucket乘积这样量级的数据给发出请求的结点,请求的结点就需要汇总3个bucket乘积再乘以16的数据量,排序后返回要的结果。 整个过程都是非常耗费CPU,内存和网路带宽的。
 
对于高cardinality字段做嵌套全量统计,一般不需要很高的计算频率,看起来场景有些不太对。

IFT8

赞同来自:

顺便请教下,像这聚合类 CPU密集型运算,目前有什么好的解决方案么?纯用ES做计算 姿势不大对

bsll

赞同来自:

聚合的时候取size:0,就会默认返回所有的结果。然后mapping用doc_value试试看。

kennywu76 - Wood^Trip.com

赞同来自:

ES5.2.0以后对于Terms aggregation引入了一个新特性,可以对cardinality很高的terms aggregation做partition,通过分批计算的方式,计算出所有的terms。 这个特性不适合实时统计的场景,但是对于数据量巨大,可以容忍计算耗时的场景比较适用。
 
参考:
https://www.elastic.co/blog/el ... eased
https://www.elastic.co/guide/e ... tions
 

要回复问题请先登录注册