概述
- 聚合分析的内部原理是什么
- aggs term avg max等执行一个聚合操作的时候,内部原理是怎样的
- 用了什么样的数据结构去执行聚合
- 是不是用的倒排索引
聚合分析原理
先来看一个搜索 + 聚合的请求1
2
3
4
5
6
7
8
9
10
11
12
13
14
15GET /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压缩
举个例子:有如下三个doc1
2
3doc1: 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
13PUT my_index
{
"mappings": {
"my_type": {
"properties": {
"my_field": {
"type": "keyword"
"doc_values": false
}
}
}
}
}