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

在采用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",

{

"key": "New Jersey",

{

"key": "New Mexico",

"doc_count": 1

}

]

}

}

}


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


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


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

例如new york被analyzed会有

ne

ew

w

y

yo

or

rk


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

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

相关文章

迭代器模式(Iterator)迭代器模式(Iterator)[Cursor]意图...
高性能IO模型浅析服务器端编程经常需要构造高性能的IO模型,...
策略模式(Strategy)策略模式(Strategy)[Policy]意图:定...
访问者模式(Visitor)访问者模式(Visitor)意图:表示一个...
命令模式(Command)命令模式(Command)[Action/Transactio...
生成器模式(Builder)生成器模式(Builder)意图:将一个对...