主要內(nèi)容: 聚合分析的內(nèi)部原理军洼,_string field聚合實(shí)驗(yàn)以及fielddata原理初探
1巩螃、聚合分析的內(nèi)部原理
doc value:正排索引
1、doc value原理
(1)index-time生成
PUT/POST的時(shí)候匕争,就會(huì)生成doc value數(shù)據(jù)避乏,也就是正排索引
(2)核心原理與倒排索引類似
正排索引,也會(huì)寫入磁盤文件中甘桑,然后呢拍皮,os cache先進(jìn)行緩存,以提升訪問doc value正排索引的性能
如果os cache內(nèi)存大小不足夠放得下整個(gè)正排索引跑杭,doc value铆帽,就會(huì)將doc value的數(shù)據(jù)寫入磁盤文件中
(3)性能問題:給jvm更少內(nèi)存,
es官方是建議德谅,es大量是基于os cache來進(jìn)行緩存和提升性能的爹橱,不建議用jvm內(nèi)存來進(jìn)行緩存,那樣會(huì)導(dǎo)致一定的gc開銷和oom問題窄做,給jvm更少的內(nèi)存愧驱,給os cache更大的內(nèi)存,os cache可以提升doc value和倒排索引的緩存和查詢效率椭盏。(64g服務(wù)器冯键,給jvm最多16g)
2、column壓縮
合并相同值庸汗,550惫确,doc1和doc2都保留一個(gè)550的標(biāo)識即可
(1)所有值相同,直接保留單值
(2)少于256個(gè)值蚯舱,使用table encoding模式:一種壓縮方式
(3)大于256個(gè)值改化,看有沒有最大公約數(shù),有就除以最大公約數(shù)枉昏,然后保留這個(gè)最大公約數(shù)
(4)如果沒有最大公約數(shù)陈肛,采取offset結(jié)合壓縮的方式:
3、disable doc value
如果的確不需要doc value兄裂,比如聚合等操作句旱,那么可以禁用,減少磁盤空間占用
PUT my_index
{
"mappings": {
"properties": {
"my_field": {
"type": "keyword",
"doc_values": false
}
}
}
}
2晰奖、_string field聚合實(shí)驗(yàn)以及fielddata原理初探(可以忽略)
對于分詞的field執(zhí)行aggregation谈撒,發(fā)現(xiàn)報(bào)錯(cuò)。匾南。啃匿。
GET /test_index/_search
{
"aggs": {
"group_by_test_field": {
"terms": {
"field": "test_field"
}
}
}
}
對分詞的field,直接執(zhí)行聚合操作,會(huì)報(bào)錯(cuò)溯乒,大概意思是說夹厌,你必須要打開fielddata,然后將正排索引數(shù)據(jù)加載到內(nèi)存中裆悄,才可以對分詞的field執(zhí)行聚合操作矛纹,而且會(huì)消耗很大的內(nèi)存
給分詞的field,設(shè)置fielddata=true光稼,可以執(zhí)行聚合
POST /test_index/_mapping/
{
"properties": {
"test_field": {
"type": "text",
"fielddata": true
}
}
}
如果對不分詞的field執(zhí)行聚合操作或南,直接就可以執(zhí)行,不需要設(shè)置fieldata=true
3钟哥、分詞field+fielddata的工作原理
(正常情況下不對未分詞的字段進(jìn)行聚合操作)
如果你的某個(gè)field不分詞,那么在index-time瞎访,就會(huì)自動(dòng)生成doc value --> 針對這些不分詞的field執(zhí)行聚合操作的時(shí)候腻贰,自動(dòng)就會(huì)用doc value來執(zhí)行
分詞的field,是沒有doc value的扒秸。播演。。在index-time伴奥,如果某個(gè)field是分詞的写烤,那么是不會(huì)給它建立doc value正排索引的,因?yàn)榉衷~后拾徙,占用的空間過于大洲炊,所以默認(rèn)是不支持分詞field進(jìn)行聚合的
如果一定要對分詞的field執(zhí)行聚合,那么必須將fielddata=true尼啡,然后es就會(huì)在執(zhí)行聚合操作的時(shí)候暂衡,現(xiàn)場將field對應(yīng)的數(shù)據(jù),建立一份fielddata正排索引崖瞭,然后基于內(nèi)存中的fielddata正排索引執(zhí)行分詞field的聚合操作
為什么fielddata必須在內(nèi)存狂巢?
分詞的字符串,需要按照term進(jìn)行聚合书聚,需要執(zhí)行更加復(fù)雜的算法和操作唧领,如果基于磁盤和os cache,那么性能會(huì)很差
3雌续、fielddata核心原理(同上斩个,忽略)
1、fielddata核心原理
fielddata加載到內(nèi)存的過程是lazy加載的驯杜,對一個(gè)analzyed field執(zhí)行聚合時(shí)萨驶,才會(huì)加載,而且是field-level加載的
一個(gè)index的一個(gè)field艇肴,所有doc都會(huì)被加載腔呜,而不是少數(shù)doc
不是index-time創(chuàng)建叁温,是query-time創(chuàng)建
2、fielddata內(nèi)存限制
indices.fielddata.cache.size: 20%核畴,超出限制膝但,清除內(nèi)存已有fielddata數(shù)據(jù)
fielddata占用的內(nèi)存超出了這個(gè)比例的限制,那么就清除掉內(nèi)存中已有的fielddata數(shù)據(jù)
默認(rèn)無限制谤草,限制內(nèi)存使用跟束,但是會(huì)導(dǎo)致頻繁evict和reload,大量IO性能損耗丑孩,以及內(nèi)存碎片和gc
3冀宴、監(jiān)控fielddata內(nèi)存使用
GET /_stats/fielddata?fields=*
GET /_nodes/stats/indices/fielddata?fields=* ##節(jié)點(diǎn)的使用情況
GET /_nodes/stats/indices/fielddata?level=indices&fields=*
4、_fielddata預(yù)加載機(jī)制(忽略吧)
如果真的要對分詞的field執(zhí)行聚合温学,那么每次都在query-time現(xiàn)場生產(chǎn)fielddata并加載到內(nèi)存中來略贮,速度可能會(huì)比較慢
我們是不是可以預(yù)先生成加載fielddata到內(nèi)存中來?仗岖?逃延?
1、fielddata預(yù)加載 (程序報(bào)錯(cuò)轧拄,遇到再研究)
POST /test_index/_mapping
{
"properties": {
"test_field": {
"type": "text",
"fielddata": {
"loading" : "eager"
}
}
}
}
query-time的fielddata生成和加載到內(nèi)存揽祥,變?yōu)閕ndex-time,建立倒排索引的時(shí)候檩电,會(huì)同步生成fielddata并且加載到內(nèi)存中來拄丰,這樣的話,對分詞field的聚合性能當(dāng)然會(huì)大幅度增強(qiáng)
2俐末、序號標(biāo)記預(yù)加載
POST /test_index/_mapping
{
"properties": {
"test_field": {
"type": "text",
"fielddata": {
"loading" : "eager_global_ordinals"
}
}
}
}