Elasticsearch-76-基于doc value正排索引的聚合内部原理

概述

  • 聚合分析的内部原理是什么
  • aggs term avg max等执行一个聚合操作的时候,内部原理是怎样的
  • 用了什么样的数据结构去执行聚合
  • 是不是用的倒排索引

聚合分析原理

先来看一个搜索 + 聚合的请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
GET /test_index/test_type/_search 
{
"query": {
"match": {
"search_field": "苹果"
}
},
"aggs": {
"group_by_agg_field": {
"terms": {
"field": "color"
}
}
}
}

采用倒排索引实现聚合的弊端

首先,es内部绝对不是用倒排索引来实现聚合分析的,先来看上面的搜索,比如说现在倒排索引中有如下数据

term doc list
苹果 doc1,doc2
小米 doc3,doc4

这时候,我们的query,只要搜索到”苹果”,拿到doc list,就停止了, 并不需要去扫描整个倒排索引.所以效率还是很高的.

然后接下来就是进行聚合,在颜色的倒排索引中去搜索,如果要找到所有的颜色的话,就必须要遍历所有的倒排索引,因为是要做分组的嘛,这个性能就十分辣鸡了

color doc list
红色 doc1
蓝色 doc2
红色 doc3
蓝色 doc4
使用倒排索引和正排索引(doc_value)来实现

首先还是和之前的query一样,从倒排索引中去搜索,拿到搜索结果之后,进行聚合,只要根据搜索的结果,一次在正排索引中去搜索,做聚合操作,比如正排索引如下:

doc color
doc1 红色
doc2 蓝色
doc3 红色
doc4 蓝色

比如搜索结果是doc1,doc2, 这时候,去正排索引中去找这两个doc,找到之后就停了,不会再继续往下找了

假设正排索引中有100万条数据,搜索结果有100条,去正排索引中去找这100条doc,比如说找到第1000条的时候,结果中的100条doc都找到了,那就没必要再去往下找了,就停了

doc_value原理

在PUT/POST数据的时候,就会生成doc_value数据,也就是正排索引

和倒排索引类似,doc_value也会写入到磁盘,先是os cache进行缓存,以提升访问doc value的性能,如果os cache内存大小不足够放的下整个doc_value,就会将doc_value的数据写入磁盘文件中

es官方建议是,es大量是基于os cache来进行缓存和提升性能的,不建议用jvm内存来进行缓存,那样会导致一定的gc开销和oom问题,给jvm更少的内存,给os cache更大的内存 ,一般64G的服务器,给jvm最多16G,剩下的给os cache,os cache可以提升doc value和倒排索引的缓存和查询效率

column压缩

举个例子:有如下三个doc

1
2
3
doc1: 550
doc2: 550
doc3: 500

会把相同的值合并掉,如doc1,doc2的值相同,就只保留一个550的标识就可以了

  • 所有值相同,直接保留单值
  • 少于256个值,使用table encoding模式(一种压缩方式)
  • 大于256个值,看有没有最大公约数,有就除以最大公约数,然后保留这个最大公约数,如果没有最大公约数,采用offset结合压缩的方式

如何禁用

有些情况下,我们可能并不需要用到doc_value,这时候就可以通过下面的请求,把doc_value禁用掉,还可以减少磁盘占用

1
2
3
4
5
6
7
8
9
10
11
12
13
PUT my_index
{
"mappings": {
"my_type": {
"properties": {
"my_field": {
"type": "keyword"
"doc_values": false
}
}
}
}
}