ElasticSearch中_source、store_fields、doc_values性能比较【转载】
原文地址请点击
在这篇文章中,我想从性能的角度探讨ElasticSearch 为我们存储了哪些字段,以及在查询检索时这些字段如何工作。实际上,ElasticSearch和Solr的底层库Lucene提供了两种存储和检索字段的方式:store_fields和doc_values。此外,ElasticSearch默认提供了 _source 字段,这是在索引时由文档的所有字段构造的一个大json。
为什么 ElasticSearch使用 _source 字段作为默认值,所有这些可用的字段从性能的角度来看有什么区别?让我们一探究竟!
Lucene中的store_fields和doc_values
当我们在 Lucene 中索引一个文档时,已经被索引的原始字段的信息丢失了。字段根据schema配置进行分词、转换然后索引形成倒排索引。没有任何额外的数据结构,当我们搜索一个文档时,我们得到的是这个文档的 docId 而不是原始字段。为了获得这些原始信息,我们需要额外的数据结构。Lucene为此提供了两种可用的方式:store_fields和doc_values。
store_fields
store_fields的目的是存储字段的原始值(没被分词),以便在查询时检索它们。正如前面所说Lucene的倒排索引查询出来的是一个个docId,为了得到原始值就得把原始值存储起来。
doc_values
引入了doc_values是为了对排序、聚合、分组等操作进行加速。doc_values也可用于在查询时返回字段值。唯一的限制是我们不能在text字段上使用doc_values。
store_fields和doc_values是在 Lucene 库中实现的,在 Solr 和 ElasticSearch 中都可以使用。
这里有一篇文章,比较了 Solr 中store_fields和doc_values检索性能:
DocValues VS Stored Fields : Apache Solr Features and Performance SmackDown.
可以找到关于store_fields和doc_values的更详细的使用方法以及各自局限性。
ElasticSearch中的字段检索
如果我们在映射中明确定义store_fields和doc_values,则可以在 elasticsearch 中使用它们:
1 |
"properties" : {
|
默认情况下,每个字段的
store都设置为 false。相反,所有支持doc_values的字段都会默认开启doc_values。
根据store_fields和doc_values的默认配置,在查询时仍然会返回查询命中的文档中的每个字段值。发生这种情况是因为 ElasticSearch 使用另一种工具进行字段检索:Elasticsearch 提供的_source字段。
ElasticSearch _source字段
_source 字段是在索引时传递给 ElasticSearch 的 json。此字段在 ElasticSearch 中默认设置为 true,可以通过以下方式使用mappings禁用_source:
1 |
"mappings": {
|
有两种方式检索_source字段的内容:
1、查询时用field选项可以提取在mappings中已经定义的字段
1 |
POST my-index-000001/_search |
还可以用format选项对一些特殊的字段进行格式化处理,比如可以将时间戳转成字符串。
这种方式命中的结果也会在的hits对象下有对应的fields字段作为响应。
1 |
{
|
2、通过_source选项提取原始的文档内容。前面的例子中,查询时_source都置成了false。
默认情况下_source为true,也就是默认返回_source原始内容的所有字段。
也可以指定要在响应中返回的_source中的一部分字段,这应该是为了提高网络传输的响应速度。
1 |
GET /_search |
可以通过适当的配置将_source的某些字段在索引的时候就排除掉:
1 |
PUT logs |
索引时,从_source中排除字段将减少磁盘空间使用,但被排除的字段将永远不会在响应中返回。
如果禁用 elasticsearch _source 字段,更新文档时需要从头开始重新索引。实际上,为了更新文档,我们需要从旧文档中获取字段的值。从逻辑上讲,使用store_fields和doc_values从旧文档中获取字段的值应该是可行的(这就是 Solr 中原子更新的工作方式)。但是,由于设计决定,这在 ElasticSearch 中是不允许的,如果您需要更新文档,则必须在 elasticsearch 索引配置中启用_source字段。
检索字段
在 elasticsearch 中,您可以启用或禁用_source字段并使Stored Field或doc_values。但是如何在查询时检索字段?
默认情况下,如果启用了_source,则返回包含整个文档的_source。您可以避免它并仅返回源的一个子集,如下所示:
1 |
POST my-index-000001/_search |
但是,如果您没有启用_source字段,并且想要从Stored Field和doc_values返回字段,则必须以另一种方式告诉它给 ElasticSearch。对于您使用的每个源,您必须以不同的方式指定字段列表:
1 |
... |
例如,如果您有一个字段既存储了store_fields也存储了doc_values,您可以选择是从store_fields还是doc_values中检索它。从功能的角度来看,这完全相同,但您的选择可能会影响查询的执行时间。
store_fields字段, doc_values和ElasticSearch _source内部结构
在本节中,我只想简要概述store_fields、_source 字段和 doc_values 的内部结构,以便来了解使用这些方法进行字段检索时对性能的期望。
store_fields内部结构
store_fields以行方式放置在磁盘中:对于每个文档,都有一行连续包含所有需要存储的字段。
img
以上图为例。为了访问文档 x 的 field3,我们必须先访问文档 x 的行起始位置,并跳过存储在 field3 之前的所有字段。跳过字段需要获取其长度。跳过字段虽然不像读取那么繁琐,但此操作并非不耗时。
doc_values内部结构
doc_values以列方式存储。多个文档的同一个字段的值一起连续存储在一起,因为同一个字段的格式基本是一致的,所以可以“几乎”直接访问某个文档的某个字段。计算一个想要的值的地址不是一个简单的操作,它有一个计算成本,但我们可以想象,如果我们只想要一个字段,使用这种访问会更有效率。但是对于磁盘来说,这种随机访问会非常影响性能,所以一般只有在排序和聚合这种需要大批量提取一个字段的情况下会使用doc_values。
ElasticSearch _source内部结构
_source 呢?好吧,如上所述,_source 是一个包含 json 的大字段,其中包含在索引时提供给 ElasticSearch 的所有输入。但是,这个字段实际上是如何存储的?毫不奇怪,ElasticSearch 利用了一种已经由 Lucene 现成的机制:store_fields。而且,_source 字段是行中第一个存储的字段。
img
正因为它是包含整个文档内容的json,所以必须读取整个_source才能使用它包含的信息。如果我们要返回一个文档的所有字段,这个过程直观上是最快的。另一方面,如果我们只需要返回它包含的信息的一小部分,读取这个巨大的字段可能会浪费计算能力。
性能测试
为了对 3 种类型的字段进行基准测试,我在 ElasticSearch 中创建了 3 个不同的索引。我索引了来自维基百科的 100 万个文档,对于每个文档,我用三种不同的方法索引了 100 个包含 15 个字符的字符串字段:在第一个索引中,我将字段设置为store_fields,在第二个索引中设置为doc_values。在这两个索引中,我都禁用了_source字段。相反,在第三个索引中,我只是启用了_source字段。
文档和查询集合来自 https://github.com/tantivy-search/search-benchmark-game。 我使用真实的集合来模拟真实的场景。
执行细节:
- CPU: AMD锐龙3600
- RAM: 32 GB
对于每个查询,我请求了最好的 200 个文档,并重复测试——将返回的字段数量(在我创建的 100 个随机字符串字段中)从 1 逐步提升到 100。
这是基准测试的结果:
img
结果正好显示了我们期望看到的结果。
1、**如果我们需要每个文档的字段很少,建议使用 doc_values **。
2、当我们想要返回整个文档_source 字段是最好的
3、而store_field是其他两者之间的完美折中。
在我执行的基准测试场景中,如果我们只需要一个字段,doc_values的速度几乎是 _source字段的两倍 ,而在相反的极端情况下,如果我们想返回所有字段,使用_source字段代替doc_values,图表显示速度几乎提高了 2倍。
总之,性能不是我们必须考虑的唯一参数。正如我们在这篇文章中简要解释的那样,使用一种或另一种方法存在一些限制。由于您的用例的一些限制,您可能被迫使用这三个中的一个。而且即使从表现来看,我们也没有明显的赢家。
如果磁盘空间不是问题,**甚至可以混合不同的方法并将字段设置为store_field和doc_values,并保持开启_source **。在查询时,elasticsearch 使您可以选择所需的字段列表,以及是否希望从 _source、_store_field或 doc_values 返回它们。
当然三个都存储,也会导致索引阶段速度很慢,容易出现EsReject异常。所以软件工程没有银弹。根据场景合适选择吧!
参考:
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-fields.html
https://sease.io/2021/02/field-retrieval-performance-in-elasticsearch.html
ElasticSearch中_source、store_fields、doc_values性能比较【转载】的更多相关文章
- Elasticsearch 中映射参数doc_values 和 fielddata分析比较
doc_values 默认情况下,大部分字段是索引的,这样让这些字段可被搜索.倒排索引(inverted index)允许查询请求在词项列表中查找搜索项(search term),并立即获得包含该词项 ...
- Elasticsearch中提升大文件检索性能的一些总结
笔者在实际生产环境中经常遇到一些大文件的检索,例如一些书籍内容,PDF文件等.今天这篇博客主要来探讨下如何提升ES在检索大文件的一些性能,经验有限,算是一个小小的总结吧! 1.大文件是多大? E ...
- Elasticsearch学习之图解Elasticsearch中的_source、_all、store和index属性
转自 : https://blog.csdn.net/napoay/article/details/62233031 1. 概述 Elasticsearch中有几个关键属性容易混淆,很多人搞不清楚_s ...
- ElasticSearch中的JVM性能调优
ElasticSearch中的JVM性能调优 前一段时间被人问了个问题:在使用ES的过程中有没有做过什么JVM调优措施? 在我搭建ES集群过程中,参照important-settings官方文档来的, ...
- Elasticsearch中最重要的文档CRUD要牢记
Elasticsearch文档CRUD要牢记 转载参考:https://juejin.im/post/5ddbf298e51d4523053c42e7 在Elasticsearch中,文档(docum ...
- 在Elasticsearch中查询Term Vectors词条向量信息
这篇文章有点深度,可能需要一些Lucene或者全文检索的背景.由于我也很久没有看过Lucene了,有些地方理解的不对还请多多指正. 更多内容还请参考整理的ELK教程 关于Term Vectors 额, ...
- Elasticsearch教程-从入门到精通(转载)
转载,原文地址:http://mageedu.blog.51cto.com/4265610/1714522?utm_source=tuicool&utm_medium=referral 各位运 ...
- ES 15 - Elasticsearch中的数据类型 (text、keyword、date、geo等)
目录 1 核心数据类型 1.1 字符串类型 - string(不再支持) 1.1.1 文本类型 - text 1.1.2 关键字类型 - keyword 1.2 数字类型 - 8种 1.3 日期类型 ...
- ElasticSearch中倒排索引和正向索引
ElasticSearch搜索使用的是倒排索引,但是排序.聚合等不适合倒排索引使用的是正向索引 倒排索引 倒排索引表以字或词为关键字进行索引,表中关键字所对应的记录项记录了出现这个字或词的所有文档,每 ...
- 使用 Elastic Agents 把定制的日志摄入到 Elasticsearch 中
转载自:https://mp.weixin.qq.com/s/QQxwYh1uLCkKn1LK72ojJA 在以前的系统中,我们可以使用如下的几种方式来采集日志: 1.我们可以直接使用 Beats 把 ...
随机推荐
- JS Leetcode 179. 最大数 题解分析,sort a-b与b-a的区别,sort排序原理解析
壹 ❀ 引 今天的题目来自LeetCode179. 最大数,题目描述如下: 给定一组非负整数 nums,重新排列每个数的顺序(每个数不可拆分)使之组成一个最大的整数. 注意:输出结果可能非常大,所以你 ...
- 【译】IEEE白皮书 6G 太赫兹技术的基本原理 2023版
第一章 简介 太赫兹波是介于微波和光波之间的光谱区域,频率从 0.1THz ~ 10THz 之间,波长在 3mm ~ 30μm 之间.提供大块连续的频带范围以满足对 Tbit/s 内极高数据传输速率的 ...
- 微信小程序云开发项目-个人待办事项-01介绍
项目简介 这个小程序项目做的是个人待办事项管理小程序,也就是大家常见的todo类程序.做这个程序主要是为了演示如何快速得学习到微信小程序一些基本得组件.路由.云函数开发技巧.有需要的朋友可以拿去自己改 ...
- centos7 安装vmware tool 遇到遇到 kernel-headers 问题修复
安装 vmware tool 步骤 1. cp VMwareTools-10.3.25-20206839.tar.gz 到 用户目录下 2. tar zxf VMwareTools-10.3.25-2 ...
- ADVMP 三代壳(vmp加固)原理分析(加壳流程)
开源项目地址 https://github.com/chago/ADVMP vmp 加固可以说时各大加固厂商的拳头产品了,这个开源项目虽然不是十分完善,让我们可以一览vmp加固的原理,是十分好的学习资 ...
- pikachu sql inject delete 注入
留言板输入几条信息 出现删除按钮,点他 通过burpsuite拦截请求,请求报文如下 GET /vul/sqli/sqli_del.php?id=57 HTTP/1.1 Host: 192.168.1 ...
- mongodb(2022)
了解 文档数据库MongoDB用于记录文档结构的数据,如JSON.XML结构的数据.一条文档就是一条记录(含数据和数据结构),一条记录里可以包含若干个键值对.键值对由键和值两部分组成,键又叫做字段.键 ...
- 【华为机试ACM基础#01】字符串最后一个单词长度、计算某字符出现次数、提取不重复的整数(熟悉字符/字符串/整数的输入)
字符串最后一个单词的长度 描述 计算字符串最后一个单词的长度,单词以空格隔开,字符串长度小于5000.(注:字符串末尾不以空格为结尾) 输入描述: 输入一行,代表要计算的字符串,非空,长度小于5000 ...
- 【LeetCode贪心#01】分饼干,贪心算法入门(入了但是还没完全入)
分饼干 力扣题目链接(opens new window) 假设你是一位很棒的家长,想要给你的孩子们一些小饼干.但是,每个孩子最多只能给一块饼干. 对每个孩子 i,都有一个胃口值 g[i],这是能让孩子 ...
- oracle不等于1怎么查?
空值null比较特殊,它不能通过=或者<>进行查询,只能用is null或者is not null进行查询,例如你的数据中有null值,那么用 字段名=1,字段名<>1,字段名 ...