1. 程式人生 > >54.string field聚合以及fielddata原理初探

54.string field聚合以及fielddata原理初探

word 設置 OS ever 磁盤 進行 fault 微軟 但是

主要知識點:

  • 直接對分詞的term進行聚合後果
  • 設置fielddata=true
  • 直接用.keyword進行聚合
  • doc value 的性能問題

一、直接對分詞的term進行聚合後果

對於分詞的field執行aggregation,發現報錯。。。

1、新建一條數據(隱式創建一個索引和type)

POST /test_index/test_type/1

{

"test_field":"test"

}

2、進行聚合操作

GET /test_index/test_type/_search

{

"aggs": {

"group_by_test_field": {

"terms": {

"field": "test_field"

}

}

}

}

執行結果如下:

{

"error": {

"root_cause": [

{

"type": "illegal_argument_exception",

"reason": "Fielddata is disabled on text fields by default. Set fielddata=true on [test_field] in order to load fielddata in memory by uninverting the inverted index. Note that this can however use significant memory."

}

對分詞的field直接執行聚合操作es會報錯,錯誤信息中會說,必須要打開fielddata(fielddata=true),然後將正排索引數據加載到內存中,才可以對分詞的field執行聚合操作,而且會消耗很大的內存

二、設置fielddata=true

1、給分詞的field,設置fielddata=true

POST /test_index/_mapping/test_type

{

"properties": {

"test_field": {

"type": "text",

"fielddata": true

}

}

}

2、查看mapping

GET /test_index/_mapping/test_type

執行結果

{

"test_index": {

"mappings": {

"test_type": {

"properties": {

"test_field": {

"type": "text",

"fields": {

"keyword": {

"type": "keyword",

"ignore_above": 256

}

},

"fielddata": true

}

}

}

}

}

}

3、再次執行聚合操作

GET /test_index/test_type/_search

{

"size": 0,

"aggs": {

"group_by_test_field": {

"terms": {

"field": "test_field"

}

}

}

}

執行結果如下:

"aggregations": {

"group_by_test_field": {

"doc_count_error_upper_bound": 0,

"sum_other_doc_count": 0,

"buckets": [

{

"key": "test",

"doc_count": 2

}

]

}

}

}

可以看出如果要對分詞的field執行聚合操作,必須將fielddata設置為true

三、直接用.keyword進行聚合

1、使用內置field不分詞,對string field進行聚合。在es新版本中,新對text的字段新建一個.keyword的字段,可以直接用這個字段進行聚合操作

GET /test_index/test_type/_search

{

"size": 0,

"aggs": {

"group_by_test_field": {

"terms": {

"field": "test_field.keyword"

}

}

}

}

執行結果如下:

"aggregations": {

"group_by_test_field": {

"doc_count_error_upper_bound": 0,

"sum_other_doc_count": 0,

"buckets": [

{

"key": "test",

"doc_count": 2

}

]

}

}

}

可以看出此時就已經可以聚合。如果對不分詞的field執行聚合操作,直接就可以執行,不需要設置fieldata=true

四、分詞field+fielddata的工作原理

在es內部會對所有不分詞的field建立doc value,這些不分詞的field可以執行聚合操作,如果某一個field不分詞,那麽在新建index的時候就已經建立了doc value值,所以es針對不分詞的field會自動使用doc value來執行聚合操作。

對於分詞field,是沒有doc value的,在新建索引時,如果某個field是分詞的,那麽es是不會給它建立doc value正排索引的,因為分詞後,占用的空間過於大,所以默認是不支持分詞field進行聚合。對於分詞field,必須打開和使用fielddata,完全存在於純內存中結構和doc value類似,如果是ngram或者是大量term,那麽必將占用大量的內存,性能會變的很差。

如果一定要對分詞的field執行聚合,那麽必須將fielddata=true,然後es就會在執行聚合操作的時候,現場將field對應的數據,建立一份fielddata正排索引,fielddata正排索引的結構跟doc value是類似的,但是只會將fielddata正排索引加載到內存中來,然後基於內存中的fielddata正排索引執行分詞field的聚合操作。這種方式會耗費大量的內存空間。

為什麽fielddata必須在內存?因為分詞的字符串,需要按照term進行聚合,需要執行更加復雜的算法和操作,如果基於磁盤和os cache,那麽性能會很差。

54.string field聚合以及fielddata原理初探