02-aggregation-and-analysis-es控制聚合内存使用-elasticsearch权威指南翻译

来源:互联网 时间:1970-01-01


在采用es的bucket agg的时候,我们会经常操作string类型的字段,一个string字段设置为analyzed和not_analyzed对聚合有什么样的影响呢?

结论是影响非常大。下面是一个例子,先bulk进一批数据

POST /agg_analysis/data/_bulk

{ "index": {}}

{ "state" : "New York" }

{ "index": {}}

{ "state" : "New Jersey" }

{ "index": {}}

{ "state" : "New Mexico" }

{ "index": {}}

{ "state" : "New York" }

{ "index": {}}

{ "state" : "New York" }

然后通过term聚合去获取结果

GET /agg_analysis/data/_search?search_type=count

{

    "aggs" : {

        "states" : {

            "terms" : {

                "field" : "state"

            }

        }

    }

}

结果是:

{

...

   "aggregations": {

      "states": {

         "buckets": [

            {

               "key": "new",

               "doc_count": 5

            },

            {

               "key": "york",

               "doc_count": 3

            },

            {

               "key": "jersey",

               "doc_count": 1

            },

            {

               "key": "mexico",

               "doc_count": 1

            }

         ]

      }

   }

}


这可不是我们想要的,聚合竟然是根据每个单词聚合的,为啥会这样?原因很简单:聚合的数据是从倒排索引中建立的,而倒排索引的数据是analyzed的。

我们需要做的是重新设置mapping

DELETE /agg_analysis/

PUT /agg_analysis

{

  "mappings": {

    "data": {

      "properties": {

        "state" : {

          "type": "string",

          "fields": {

            "raw" : {

              "type": "string",

              "index": "not_analyzed"

            }

          }

        }

      }

    }

  }

}


POST /agg_analysis/data/_bulk

{ "index": {}}

{ "state" : "New York" }

{ "index": {}}

{ "state" : "New Jersey" }

{ "index": {}}

{ "state" : "New Mexico" }

{ "index": {}}

{ "state" : "New York" }

{ "index": {}}

{ "state" : "New York" }


GET /agg_analysis/data/_search?search_type=count

{

  "aggs" : {

    "states" : {

        "terms" : {

            "field" : "state.raw" 

        }

    }

  }

}



This time we explicitly map the state field and include a not_analyzed sub-field.




The aggregation is run on state.raw instead of state.


Now when we run our aggregation, we get results that make sense:


{

...

   "aggregations": {

      "states": {

         "buckets": [

            {

               "key": "New York",

               "doc_count": 3

            },

            {

               "key": "New Jersey",

               "doc_count": 1

            },

            {

               "key": "New Mexico",

               "doc_count": 1

            }

         ]

      }

   }

}


在日常开发中这种问题总会出现,你要记住这个issue,通常,很少会有业务使用分析字段做聚合的,如果真的出现,你的做法就是加个字段然后同样的值然后分别使用即可。


high-cardinality memory  implications 极其重要的内存潜在问题


这里还有个重要的理由避免聚合analyzed字段,因为把这些字段加入fielddata之后会占用大量的内存,这分析过程会生成大量的token,每个token都是独立的,大量的数据会占用大量的内存。

例如new york被analyzed会有

ne

ew

 y

yo

or

rk


你可以想象这是多么可怕,特别是在分析段落字段的时候(例如商品描述),很容易造成内存溢出。

所以,在通过这些字段聚合之前,核对这个字段是否是analyzed的,不管是不是analzyzed的,越长的string字段绝对内存占用越大,所以得注意一下。



相关阅读:
Top