elasticsearch的Doc Values 和 Fielddata

2024-04-01 07:18

本文主要是介绍elasticsearch的Doc Values 和 Fielddata,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

DocValues

什么是DocValues

简单说明DocValues就是一个种列式的数据存储结构(docid、termvalues)。
倒排索引的优势在于查找包含某个项的文档,即通过Term查找对应的docid。

term的倒排

TermDoc_1Doc_2Doc_3
brownXX
dogX

term2的倒排

Term2Doc_1Doc_2Doc_3
brown2XX
dog2X

如此能够快速定位包含brown的文档为doc1和doc2。

但是对于从另外一个方向的相反操作并不高效,即根据docid找到该文档的指定字段(Term2)的值是什么。但是聚合、排序和明细查询等时候需要这种的访问模式。
声明遍历索引是不可取。这很慢而且难以扩展:随着词项和文档的数量增加,执行时间也会增加。为了能够解决上述问题,我们使用了Doc values,通过转置两者间的关系来解决这个问题。
term的docvalues

DocTerm
Doc_1brown
Doc_2brown
Doc_3dog

term2的docvalues

DocTerm2
Doc_1brown2
Doc_2brown2
Doc_3dog2

举例说明:

select term2,count(1) from table where Term=’brown’ group by term2

如要完成类似上述sql的聚合查询,则:
1. 定位数据范围。检索到Term=’brown’的docid(doc1,doc2),此时使用倒排索引
2. 进行聚合计算。根据doc1,doc2定位到term2的字段均为brown2,进行聚合累加得到计算结果。browm2的count(1)=2。

搜索和聚合是相互紧密关联的。搜索使用倒排索引查找文档,聚合操作收集和聚合 doc values 里的数据。

DocValues是如何工作的

DocValues的官方文档介绍特点为fast, efficient and memory-friendly。
1、DocValues是在索引时与倒排索引同时生成的,并且是不可变的。与倒排一样,保存在lucene文件中(序列化到磁盘)。
lucene文件操作依赖于操作系统的缓存来管理,而不是在 JVM 堆栈里驻留数据。 这个特点决定了在使用es时候要分配足够内存给os,保证文件处理性能,详细设置可以参照 生产环境elasticsearch的配置建议

2、DocValues使用列式压缩
现代 CPU 的处理速度要比磁盘快几个数量级, 这意味着减少必须从磁盘读取的数据量总是有益的,尽管需要额外的 CPU 运算来进行解压。

DocValues使用了很多压缩技巧。它会按依次检测以下压缩模式:
- 如果所有的数值各不相同(或缺失),设置一个标记并记录这些值
- 如果这些值小于 256,将使用一个简单的编码表
- 如果这些值大于256,检测是否存在一个最大公约数
- 如果没有存在最大公约数,从最小的数值开始,统一计算偏移量进行编码
这些压缩模式不是传统的通用的压缩方式,比如 DEFLATE 或是 LZ4。 因为列式存储的结构是严格且良好定义的,我们可以通过使用专门的模式来达到比通用压缩算法(如 LZ4 )更高的压缩效果。

,字符类型通过借助顺序表(ordinal table)进行类似编码的。字符类型是去重之后存放到顺序表的,通过分配一个 ID,然后这些 ID 和数值类型的文档值一样使用。 也就是说,字符类型和数值类型一样拥有相同的压缩特性。
顺序表本身也有很多压缩技巧,比如固定长度、变长或是前缀字符编码等等。

3、DocValues支持禁用
此值默认是启动状态,如果没有必要使用可以设置 doc_values: false来禁用。

DocValues不支持的

根据上面介绍,Doc values 是不支持 analyzed 字符串字段的,想象一下,如果一个字段是analyzed,如the first,则在分析阶段则会docvalues则会存储为两条docvalue(the和first),计算时候则会得到

termcount
the1
first1

而不是

termcount
the first1

那想要怎么达到我们想要的结果呢?fielddata。

Fielddata

doc values 不生成分析的字符串,然而,这些字段仍然可以使用聚合,是因为使用了fielddata 的数据结构。与 doc values 不同,fielddata 构建和管理 100% 在内存中,常驻于 JVM 内存堆。fielddata 是 所有 字段的默认设置。

注意内存使用

一些特性:
1. Fielddata 是延迟加载的。如果你从来没有聚合一个分析字符串,就不会加载 fielddata 到内存中,是在查询时候构建的。
2. fielddata 是基于字段加载的, 只有很活跃地使用字段才会增加fielddata 的负担。
3. fielddata 会加载索引中(针对该特定字段的) 所有的文档,而不管查询是否命中。逻辑是这样:如果查询会访问文档 X、Y 和 Z,那很有可能会在下一个查询中访问其他文档。
4. 如果空间不足,使用最久未使用(LRU)算法移除fielddata。
所以,fielddata应该在JVM中合理利用,否则会影响es性能。
我们可以使用indices.fielddata.cache.size限制fielddata内存使用,可以是具体大小(如2G),也可以是占用内存的百分比(如20%)。
也可以使用如下命令进行监控。

GET /_stats/fielddata

最后,如果一次性加载字段直接超过内存值会发生什么?挂掉?所以es为了防止这种情况,采用了circuit breaker(熔断机制)。
它通过内部检查(字段的类型、基数、大小等等)来估算一个查询需要的内存。它然后检查要求加载的 fielddata 是否会导致 fielddata 的总量超过堆的配置比例。如果估算查询大小超出限制,就会触发熔断,查询会被中止并返回异常。

indices.breaker.fielddata.limit fielddata级别限制,默认为堆的60%
indices.breaker.request.limit request级别请求限制,默认为堆的40%
indices.breaker.total.limit 保证上面两者组合起来的限制,默认堆的70%

Fielddata过滤

通过设置可以只加载部分fielddata来节省内存。

“frequency”: {
“min”: 0.01,
“min_segment_size”: 500
}
只加载那些至少在本段文档中出现 1% 的项。
忽略任何文档个数小于 500 的段。
详细参照官网。

Fielddata预加载

加载fielddata默认是延迟加载 。 当 Elasticsearch 第一次查询某个字段时,它将会完整加载这个字段所有 Segment中的倒排索引到内存中,以便于以后的查询能够获取更好的性能。
对于小索引段来说,这个过程的需要的时间可以忽略。但如果索引很大几个GB,这个过程可能会要数秒。对于 已经习惯亚秒响应的用户很难会接受停顿数秒卡顿。
有三种方式可以解决这个延时高峰:

  1. 预加载 fielddata,设置提前加载。
  2. 预加载全局序号。一种减少内存占用的加载优化方式,类似于一种全局字典(存储string字段和其对应的全局唯一int值),这样只加载int值,然后查找字典中的对应的string字段。
  3. 缓存预热。已经弃用。

这篇关于elasticsearch的Doc Values 和 Fielddata的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/866546

相关文章

Java实现Elasticsearch查询当前索引全部数据的完整代码

《Java实现Elasticsearch查询当前索引全部数据的完整代码》:本文主要介绍如何在Java中实现查询Elasticsearch索引中指定条件下的全部数据,通过设置滚动查询参数(scrol... 目录需求背景通常情况Java 实现查询 Elasticsearch 全部数据写在最后需求背景通常情况下

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

MFC中App,Doc,MainFrame,View各指针的互相获取

纸上得来终觉浅,为了熟悉获取方法,我建了个SDI。 首先说明这四个类的执行顺序是App->Doc->Main->View 另外添加CDialog类获得各个指针的方法。 多文档的获取有点小区别,有时间也总结一下。 //  App void CSDIApp::OnApp() {      //  App      //  Doc     CDocument *pD

ElasticSearch的DSL查询⑤(ES数据聚合、DSL语法数据聚合、RestClient数据聚合)

目录 一、数据聚合 1.1 DSL实现聚合 1.1.1 Bucket聚合  1.1.2 带条件聚合 1.1.3 Metric聚合 1.1.4 总结 2.1 RestClient实现聚合 2.1.1 Bucket聚合 2.1.2 带条件聚合 2.2.3 Metric聚合 一、数据聚合 聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如:

【docker】基于docker-compose 安装elasticsearch + kibana + ik分词器(8.10.4版本)

记录下,使用 docker-compose 安装 Elasticsearch 和 Kibana,并配置 IK 分词器,你可以按照以下步骤进行。此过程适用于 Elasticsearch 和 Kibana 8.10.4 版本。 安装 首先,在你的工作目录下创建一个 docker-compose.yml 文件,用于配置 Elasticsearch 和 Kibana 的服务。 version:

ElasticSearch底层原理简析

1.ElasticSearch简述 ElastiaSearch(以下简称ES)是一个基于Lucene的搜索服务器,它提供了一个分布式多用户能力的全文搜索引擎,支持RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。ES设计用于云计算中,能够进行实时搜索,支持PB级搜索,具有稳定,可靠,快速,安装使用方便等

ElasticSearch 6.1.1 通过Head插件,新建索引,添加文档,及其查询数据

ElasticSearch 6.1.1 通过Head插件,新建索引,添加文档,及其查询; 一、首先启动相关服务: 二、新建一个film索引: 三、建立映射: 1、通过Head插件: POST http://192.168.1.111:9200/film/_mapping/dongzuo/ {"properties": {"title": {"type":

ElasticSearch 6.1.1运用代码添加索引及其添加,修改,删除文档

1、新建一个MAVEN项目:ElasticSearchTest 2、修改pom.xml文件内容: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.or

Windows下安装Elasticsearch,启动报错,解决方法,访问

对于Windows用户,我们推荐使用MSI安装包进行安装。这个安装包使用图形用户界面来引导你进行安装。 首先,从这里https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.1.1.msi下载Elasticsearch 6.1.1的MSI安装包。 然后双击下载好的安装包文件启动图形化安装程序,在第一个界面,选