ElasticSearch中_source、store_fields、doc_values性能比较

标签: 数据库 DB ElasticSearch Lucene | 发表时间:2021-10-22 00:00 | 作者:
出处:https://blog.hufeifei.cn/

为什么 ElasticSearch使用 _source 字段作为默认值,所有这些可用的字段从性能的角度来看有什么区别?让我们一探究竟!

#lucene中的stored和doc_values

当我们在 Lucene 中索引一个文档时,已经被索引的原始字段的信息丢失了。字段根据schema配置进行分词、转换然后索引形成倒排索引。没有任何额外的数据结构,当我们搜索一个文档时,我们得到的是被搜索文档的 id 而不是原始字段。为了获得这些原始信息,我们需要额外的数据结构。Lucene为此提供了两种可用的方式:Stored Field和doc_values。

#Stored Field

Stored Field的目的是存储字段的原始值(没被分词),以便在查询时检索它们。

#doc_values

引入了 doc_values 是为了对一些操作进行加速,例如faceting、sorting和grouping。doc_values 也可用于在查询时返回字段值。唯一的限制是我们不能在text字段上使用doc_values。

Stored Field和doc_values是在 Lucene 库中实现的,它们可以在 Solr 和 ElasticSearch 中使用。

我写了一篇博文,比较了 Solr 中Stored Field和doc_values检索性能:

DocValues VS Stored Fields : Apache Solr Features and Performance SmackDown.

您可以找到关于存储字段和文档值、它们的使用和约束的更详细的描述。

#ElasticSearch中的字段检索

如果我们在映射中明确定义存储的字段和文档值,则可以在 elasticsearch 中使用它们:

1      
2
3
4
5
6
7
"properties" : {      
"field": {
"type": "keyword",
"store": true,
"doc_values" true
}
}

默认情况下, 每个字段的 store都设置为 false。相反, 所有支持 doc_values的字段都会默认开启 doc_values

根据Stored Field和doc_values的默认配置,在查询时仍然会返回查询命中的文档中的每个字段值。发生这种情况是因为 ElasticSearch 使用另一种工具进行字段检索: elasticsearch _source字段。

#elasticsearch _source 字段

_source 字段是在索引时传递给 ElasticSearch 的 json。此字段在 ElasticSearch 中默认设置为 true,可以通过以下方式使用 mappings禁用:

1      
2
3
4
5
"mappings": {      
"_source": {
"enabled": false
}
}

查询时默认返回所有字段。您也可以 指定要在响应中返回的 _source中的一部分字段,这应该是为了提高网络传输的响应速度。

1      
2
3
4
5
6
7
8
9
10
11
12
GET /_search      
{
"_source": {
"includes": [ "obj1.*", "obj2.*" ],
"excludes": [ "*.description" ]
},
"query": {
"term": {
"user.id": "kimchy"
}
}
}

可以 通过适当的配置将 _source的某些字段排除

1      
2
3
4
5
6
7
8
9
10
11
PUT logs      
{
"mappings": {
"_source": {
"excludes": [
"meta.description",
"meta.other.*"
]
}
}
}

_source中排除字段将减少磁盘空间使用,但被排除的字段将永远不会在响应中返回。

禁用 elasticsearch _source 字段,更新文档需要从头开始重新索引。实际上,为了更新文档,我们需要从旧文档中获取字段的值。从逻辑上讲,使用Stored Field和doc_values从旧文档中获取字段的值应该是可行的(这就是 Solr 中原子更新的工作方式)。但是,由于设计决定,这在 ElasticSearch 中是不允许的,如果您需要更新文档,则必须在 elasticsearch 索引配置中启用 _source字段。

#检索字段

在 elasticsearch 中,您可以启用或禁用 _source字段并使Stored Field或 doc_values。但是如何在查询时检索字段?

默认情况下,如果启用了 _source,则返回包含整个文档的 _source。您可以避免它并仅返回源的一个子集,如下所示:

1      
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
POST my-index-000001/_search      
{
"query": {
"match": {
"user.id": "kimchy"
}
},
"fields": [
"user.id",
"http.response.*",
{
"field": "@timestamp",
"format": "epoch_millis"
}
],
"_source": false
}

但是,如果您没有启用 _source字段,并且想要从Stored Field和 doc_values返回字段,则必须以另一种方式告诉它给 ElasticSearch。对于您使用的每个源,您必须以不同的方式指定字段列表:

1      
2
3
4
5
...      
"fields": ["sv1", "sv2",...],
"docvalue_fields": ["dv1", "dv2",...],
"stored_fields" : ["s1", "s2",...],
...

例如,如果您有一个字段既存储了Stored Field也存储了doc_values,您可以选择是从Stored Field还是doc_values中检索它。从功能的角度来看,这完全相同,但您的选择可能会影响查询的执行时间。

#stored 字段, doc_values和ElasticSearch _source内部形式

在本节中,我只想简要概述Stored Field、 _source 字段和 doc_values 的内部结构,以便获得一些工具来了解使用这些方法进行字段检索时对性能的期望。

#stored内部结构

存储的字段以行方式放置在磁盘中:对于每个文档,我们有一行连续包含所有存储的字段。

img

以上图为例。为了访问文档 x 的 field3,我们必须访问文档 x 的行并跳过存储在 field3 之前的所有字段。跳过字段需要获取其长度。跳过字段虽然不像读取那么繁琐,但此操作并非不耗时。

#Doc_values内部结构

文档值以列方式存储。不同文档的相同字段的值一起连续存储在内存中,并且可以“几乎”直接访问某个文档的某个字段。计算一个想要的值的地址不是一个简单的操作,它有一个计算成本,但我们可以想象,如果我们只想要一个字段,使用这种访问会更有效率。

#ElasticSearch _source内部结构

_source 呢?好吧,如上所述,源是一个包含 json 的大字段,其中包含在索引时提供给 ElasticSearch 的所有输入。但是,这个字段实际上是如何存储的?毫不奇怪,elasticsearch 利用了一种已经由 lucene 实现和提供的机制:Stored Field。而且, _source 字段是行中第一个存储的字段。

img

必须阅读整个 _source 才能使用它包含的信息。如果我们要返回一个文档的所有字段,这个过程直观上是最快的。另一方面,如果我们只需要返回它包含的信息的一小部分,读取这个巨大的字段可能会浪费计算能力。

#性能测试

为了对 3 种类型的字段进行基准测试,我在 ElasticSearch 中创建了 3 个不同的索引。我索引了来自维基百科的 100 万个文档,对于每个文档,我用三种不同的方法索引了 100 个包含 15 个字符的字符串字段:在第一个索引中,我将字段设置为存储,在第二个索引中设置为 docvalues。在这两个索引中,我都禁用了源字段。相反,在第三个索引中,我只是启用了源字段。

文档和查询集合来自 https://github.com/tantivy-search/search-benchmark-game。 我使用真实的集合来模拟真实的场景。

执行细节:

  • CPU: AMD锐龙3600
  • RAM: 32 GB

对于每个查询,我请求了最好的 200 个文档,并重复测试,将要返回的字段数量(在我创建的 100 个随机字符串字段中)从 1 更改为 100。

这是基准测试的结果:

img

结果正好显示了我们期望看到的结果。 如果我们需要每个文档的字段很少,建议使用 Docvalues。另一方面, 当我们想要返回整个文档_source 字段是最好的,而 store_field的使用是其他两者之间的完美折衷。

在我执行的基准测试场景中, 如果我们只需要一个字段docvalues 的速度几乎是 _source 字段的两倍 ,而在相反的极端情况下,如果我们想返回所有字段,图表显示当我们需要时,速度几乎提高了 2倍使用 _source 字段代替 docvalues。

总之,性能不是我们必须考虑的唯一参数。正如我们在这篇博文中简要解释的那样,使用一种或另一种方法存在一些限制。由于您的用例的一些限制,您可能被迫使用这三个中的一个。而且即使从表现来看,我们也没有明显的赢家。

如果磁盘空间不是问题, 您甚至可以混合不同的方法并将字段设置为存储和文档值,并保持_source启用。在查询时,elasticsearch 使您可以选择所需的字段列表,以及是否希望从 _source_store_fielddoc_values 返回它们。

参考:

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] 推荐:

Elasticsearch 與 Kibana 也變成非 Open Source 軟體

- - Gea-Suan Lin's BLOG
從 Nuzzel 上看到的消息, Elasticsearch 與 Kibana 也變成非 Open Source 軟體了:「 Elasticsearch and Kibana are now business risks」,官方的公告在「 Upcoming licensing changes to Elasticsearch and Kibana」這邊.

DS-Source

- - Darren观测站
中国统计年鉴 基本有中国历年各方面的所有数据. 统计学领域论文或书籍中的数据集. R包中的数据集,比如women、mtcars. 加州大学欧文分校机器学习库. Google Datasets 里面也有商用的数据库. 世界银行 免费并公开获取世界各国的发展数据.. 列出了全世界许多开放数据库. Kaggle 提供一个数据搜索引擎.

JavaScript Source Map 详解

- - 阮一峰的网络日志
上周, jQuery 1.9发布. 这是2.0版之前的最后一个新版本,有很多新功能,其中一个就是支持Source Map. 访问 http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js,打开压缩后的版本,滚动到底部,你可以看到最后一行是这样的:.

GitHub - jgraph/drawio: Source to www.draw.io

- -
draw.io supports IE 11, Chrome 32+, Firefox 38+, Safari 9.1.x, 10.1.x and 11.0.x, Opera 20+, Native Android browser 5.1.x+, the default browser in the current and previous major iOS versions (e.g.

我的open source專案整理列表

- Charles - 程式設計 遇上 小提琴
HGE以前是一款商用的2D遊戲引擎,後來開源,因為我覺得他的引擎挺簡單好用的,重點是有硬體加速,不像SDL純軟體算圖很慢,所以想說把它移植到Python,於是就用Boost.Python寫了一個專案,完成度大約7~8成,裡面有些比較難處理的部份還沒弄好,但主要功能大多都已經可以使用. Glottony是一個用來分析Python函式庫在PyPi上的相依情況,主要是有一次我安裝TurboGears時遇到其中一個package的伺服器似乎掛掉了,整個進度就因為那個檔案載不了而無法進行,因此我覺得或許這種相依的情況也是選工具時重要的考量,於是就寫了這樣的工具.

BigBlueButton 安装笔记|Installing from source

- - 移动开发 - ITeye博客
bigbluebutton是一个万维网广播站和会议系统,他是基于Flash的视频会议,后台服务器使用Red5 Server. 本篇是参考installing from source英文版,根据自己的情况有点改动,系统是基于ubuntu之上. 如果想在ubuntu上快安装bigbluebutton请参见英文文档:http://code.google.com/p /bigbluebutton/wiki/InstallationUbuntu.

GitHub - smartnews/jpa-entity-generator: Lombok-wired JPA entity source code generator, Gradle and Maven supported.

- -
If you need to make sure if your latest code works with sample project or your existing projects, run the following command to publish the latest build to the local Maven repository..

[译]elasticsearch mapping

- - an74520的专栏
es的mapping设置很关键,mapping设置不到位可能导致索引重建. 请看下面各个类型介绍^_^. 每一个JSON字段可以被映射到一个特定的核心类型. JSON本身已经为我们提供了一些输入,支持 string,  integer/ long,  float/ double,  boolean, and  null..

Elasticsearch as Database - taowen - SegmentFault

- -
【北京上地】滴滴出行基础平台部招聘 Elasticsearch 与 Mysql binlog databus 开发工程师. 内推简历投递给: [email protected]. 推销Elasticsearch. 时间序列数据库的秘密(1)—— 介绍. 时间序列数据库的秘密(2)——索引.

ロンドンに「Google Store」オープン

- 三十不归 - スラッシュドット・ジャパン
capra 曰く、AppleやMicrosoftに続き、Googleも同社世界初となる「Google Store」をオープンさせたそうだ(London Evening Standard、本家/.). 第一弾は英国ロンドンの「ガジェットストリート」なるTottenham Court Roadに登場したとのこと.