ElasticSearch实战笔记

34、聚合分析的内部原理,_string field聚合实验以及

2020-04-18  本文已影响0人  众神开挂

主要内容: 聚合分析的内部原理,_string field聚合实验以及fielddata原理初探

1、聚合分析的内部原理

doc value:正排索引

1、doc value原理

(1)index-time生成

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

(2)核心原理与倒排索引类似

正排索引,也会写入磁盘文件中,然后呢,os cache先进行缓存,以提升访问doc value正排索引的性能
如果os cache内存大小不足够放得下整个正排索引,doc value,就会将doc value的数据写入磁盘文件中

(3)性能问题:给jvm更少内存,

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

2、column压缩

合并相同值,550,doc1和doc2都保留一个550的标识即可

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

3、disable doc value

如果的确不需要doc value,比如聚合等操作,那么可以禁用,减少磁盘空间占用

PUT my_index
{
  "mappings": {
    "properties": {
      "my_field": {
        "type": "keyword",
        "doc_values": false
      }
    }
  }
}

2、_string field聚合实验以及fielddata原理初探(可以忽略)

对于分词的field执行aggregation,发现报错。。。

GET /test_index/_search 
{
  "aggs": {
    "group_by_test_field": {
      "terms": {
        "field": "test_field"
      }
    }
  }
}

对分词的field,直接执行聚合操作,会报错,大概意思是说,你必须要打开fielddata,然后将正排索引数据加载到内存中,才可以对分词的field执行聚合操作,而且会消耗很大的内存

给分词的field,设置fielddata=true,可以执行聚合

POST /test_index/_mapping/ 
{
  "properties": {
    "test_field": {
      "type": "text",
      "fielddata": true
    }
  }
}

如果对不分词的field执行聚合操作,直接就可以执行,不需要设置fieldata=true

3、分词field+fielddata的工作原理

(正常情况下不对未分词的字段进行聚合操作)

如果你的某个field不分词,那么在index-time,就会自动生成doc value --> 针对这些不分词的field执行聚合操作的时候,自动就会用doc value来执行

分词的field,是没有doc value的。。。在index-time,如果某个field是分词的,那么是不会给它建立doc value正排索引的,因为分词后,占用的空间过于大,所以默认是不支持分词field进行聚合的

如果一定要对分词的field执行聚合,那么必须将fielddata=true,然后es就会在执行聚合操作的时候,现场将field对应的数据,建立一份fielddata正排索引,然后基于内存中的fielddata正排索引执行分词field的聚合操作

为什么fielddata必须在内存?

分词的字符串,需要按照term进行聚合,需要执行更加复杂的算法和操作,如果基于磁盘和os cache,那么性能会很差

3、fielddata核心原理(同上,忽略)

1、fielddata核心原理

fielddata加载到内存的过程是lazy加载的,对一个analzyed field执行聚合时,才会加载,而且是field-level加载的
一个index的一个field,所有doc都会被加载,而不是少数doc
不是index-time创建,是query-time创建

2、fielddata内存限制

indices.fielddata.cache.size: 20%,超出限制,清除内存已有fielddata数据
fielddata占用的内存超出了这个比例的限制,那么就清除掉内存中已有的fielddata数据
默认无限制,限制内存使用,但是会导致频繁evict和reload,大量IO性能损耗,以及内存碎片和gc

3、监控fielddata内存使用

GET /_stats/fielddata?fields=* 
GET /_nodes/stats/indices/fielddata?fields=* ##节点的使用情况
GET /_nodes/stats/indices/fielddata?level=indices&fields=*

4、_fielddata预加载机制(忽略吧)

如果真的要对分词的field执行聚合,那么每次都在query-time现场生产fielddata并加载到内存中来,速度可能会比较慢

我们是不是可以预先生成加载fielddata到内存中来???

1、fielddata预加载 (程序报错,遇到再研究)

POST /test_index/_mapping
{
  "properties": {
    "test_field": {
      "type": "text",
      "fielddata": {
        "loading" : "eager" 
      }
    }
  }
}

query-time的fielddata生成和加载到内存,变为index-time,建立倒排索引的时候,会同步生成fielddata并且加载到内存中来,这样的话,对分词field的聚合性能当然会大幅度增强

2、序号标记预加载

POST /test_index/_mapping
{
  "properties": {
    "test_field": {
      "type": "text",
      "fielddata": {
        "loading" : "eager_global_ordinals" 
      }
    }
  }
}
上一篇下一篇

猜你喜欢

热点阅读