文章目录


白话Elasticsearch50-深入聚合数据分析之基于doc values正排索引的聚合内部原理_doc values


概述

继续跟中华石杉老师学习ES,第50篇

思考

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


知识点

ES搜索靠倒排索引。 排序的时候,需要依靠正排索引,看到每个document的每个field,然后进行排序,所谓的正排索引,其实就是doc values。

ES在建立索引的时候,

  • 一方面会建立倒排索引,以供搜索用
  • 一方面会建立正排索引,也就是doc values,以供排序,聚合,过滤等操作使用

doc values是被保存在磁盘上的,此时如果内存足够,os会自动将其缓存在内存中,性能还是会很高,若内存不足,os会将其写入磁盘。


举例说明

举一个 搜索+聚合 的例子 来理解下 倒排索引和正排索引。

GET /test_index/test_type/_search 
{
"query": {
"match": {
"search_field": "test"
}
},
"aggs": {
"group_by_agg_field": {
"terms": {
"field": "agg_field"
}
}
}
}

那上面的DSL举个例子

假设索引中有3个doc

doc1: hello world test1, test2
doc2: hello test
doc3: world test

那ES建立的倒排索引如下:

hello --->  doc1,doc2
world ---> doc1,doc3
test1 ---> doc1
test2 ---> doc1
test ---> doc2,doc3

我们的DSL中的查询

"query": {
"match": {
"search_field": "test"
}
}

查询 “test” ,那么直接从倒排索引中查到对应的结果为doc2,doc3 ,那么搜索就是 doc2,doc3 。


纯用倒排索引来实现的弊端

先回归下,最简单的aggs操作

白话Elasticsearch50-深入聚合数据分析之基于doc values正排索引的聚合内部原理_倒排索引_02

请求DSL中, ​​"field": "color"​​ ,按照某个字段划分bucket操作,

返回结果是 该field对应的value ,每个value对应一个bucket .

那我们上面的例子中的 aggs呢 ? 假设也是 倒排索引的方式来查找,我们来分析下

agg_field

假设如下N多个doc:

...
...
...
...N多doc
doc2: agg_field_value_1
doc3: agg_field_value_2

那建立的倒排索引 如下

...
...
...
...
...N多值
agg_field_value_1 doc2
agg_field_value_2 doc3

doc2, doc3, search result --> 实际上,要搜索到doc2的agg_field的值是多少,doc3的agg_field的值是多少

拿到doc2和doc3的agg_field的值之后,就可以根据值进行分组,实现terms bucket操作

doc2的agg_field的值是多少,这个时候,如果你手上只有一个倒排索引,你该怎么办???你要扫描整个倒排索引,去一个一个的搜,拿到每个值,比如说agg_field_value_1 ,看一下,它是不是doc2的值,拿到agg_field_value_2,看一下,是不是doc2的值,直到在倒排索引中找到doc2的agg_field的值。

如果用纯倒排索引去实现聚合,现实不现实啊???性能是很低下的。。。搜索,search,搜倒排索引,搜那个term,就结束了。。。聚合,搜索出了1万个doc,每个doc都要在倒排索引中搜索出它的那个聚合field的值。

倒排索引的话,必须遍历完整个倒排索引才可以。。。。

因为可能你要聚合的那个field的值,是分词的,比如说hello world my name --> 一个doc的聚合field的值可能在倒排索引中对应多个value

所以说,当你在倒排索引中找到一个值,发现它是属于某个doc的时候,还不能停,必须遍历完整个倒排索引,才能说确保找到了每个doc对应的所有terms,然后进行分组聚合


倒排索引+正排索引(doc value)的原理和优势

正排索引 如下:

document

agg_field

doc1

agg_fiele_value1

doc2

agg_fiele_value2

1万个doc --> 搜 -> 可能跟搜索到15000次,就搜索完了,就找到了1万个doc的聚合field的所有值了,然后就可以执行分组聚合操作了

石杉老师说的最后一句话 ,我没明白, 为啥不用把正排索引都搜索完呢? 有明白的同仁 指导下 拜托了。