[译]Elasticsearch _source Doc_values And Store Performance

server/2025/1/15 21:42:28/

原文地址
https://sease.io/2021/02/field-retrieval-performance-in-elasticsearch.html

在这篇博文中,我想从性能的角度探讨 Elasticsearch 为我们存储字段和查询时检索字段提供了哪些可能性。 事实上,Lucene(Elasticsearch 和 Solr 构建的基础库)提供了两种存储和检索字段的方法:存储字段(stored fields)和文档值(docvalues)。 此外,Elasticsearch 默认使用 _source 字段,这是一个大 JSON,其中包含在索引时作为输入给出的文档的所有字段。

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

Stored And Docvalues Fields In Lucene

当我们在 Lucene 中索引文档时,已索引的原始字段的信息会丢失。 根据模式配置对字段进行相应的分析、转换和索引。 在没有任何额外数据结构的情况下,当我们搜索文档时,我们得到的是搜索到的文档的 id,而不是原始字段。 为了获取这些信息,我们需要额外的数据结构。 Lucene 为此提供了两种可能性:存储字段和文档值。

STORED FIELDS

存储字段的目的是存储字段的值(不进行任何分析)以便在查询时检索它们。

DOCVALUES

引入文档值是为了加速分面、排序和分组等操作。 文档值还可用于在查询时返回字段值。 我们唯一的限制是我们不能将它们用于文本字段。

存储字段和文档值在 Lucene 库中实现,它们可以在 Solr 和 Elasticsearch 中使用。

我写了一篇博客文章,其中比较了 Solr 中存储字段和文档值的字段检索性能:

DocValues VS 存储字段:Apache Solr 功能和性能 SmackDown

在那里您可以找到有关存储字段和文档值、其利用率和约束的更详细描述。

Field Retrieval In Elasticsearch

如果我们在映射中显式定义存储字段和文档值,则可以在 Elasticsearch 中使用它们:

"properties" : {"field": {"type": "keyword","store": true,"doc_values" true}
}

默认情况下,每个字段的存储设置为 false。 相反,所有支持文档值的字段都默认启用它们。

独立于存储和文档值配置,在查询时返回查询命中的文档中每个字段的值。 发生这种情况是因为 Elasticsearch 使用另一个工具进行字段检索:elasticsearch _source 字段。

ELASTICSEARCH _SOURCE FIELD

源字段是在索引时传递到 Elasticsearch 的 JSON。 该字段在 Elasticsearch 中默认设置为 true,并且可以通过以下方式使用映射来禁用:

"mappings": {"_source": {"enabled": false}
}

查询时默认返回所有字段。 您甚至可以仅指定要在响应中返回的源中的字段子集。 这应该可以加快响应在网络上的传输速度。

通过正确的配置,某些字段可以被源字段排除:

PUT logs
{"mappings": {"_source": {"excludes": ["meta.description","meta.other.*"]}}
}

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

禁用 elasticsearch _source 字段将导致无法在不从头开始重新索引的情况下更新文档(Disabling the elasticsearch _source field will make it impossible to update a document without reindexing that from scratch)。 事实上,为了更新文档,我们需要从旧文档中获取字段的值。 从逻辑上讲,使用存储的字段或文档值从旧文档中获取字段的值应该是可行的(这就是 Solr 中原子更新的工作方式)。 但是,由于设计决策,Elasticsearch 中不允许这样做,如果您需要更新文档,则必须在 Elasticsearch 索引配置中启用 _source 字段。

RETRIEVING FIELDS

在 Elasticsearch 中,您可以启用或禁用 _source 字段并使字段存储和/或文档值。 但是我们如何在查询时检索字段呢?

默认情况下,如果定义了整个源,则返回整个源。 您可以避免它并仅返回源的子集,如下所示:

 "fields": ["field1", "field2"],"_source": false

但是,如果您没有启用源字段,并且想要从存储的或文档值返回字段,则必须以其他方式告诉 Elasticsearch。 对于您使用的每个源,您必须以不同的方式指定字段列表:

 "fields": ["sv1", "sv2",...],"docvalue_fields": ["dv1", "dv2",...],"stored_fields" : ["s1", "s2",...],

例如,如果您有一个存储字段和文档值字段,您可以选择是否要从文档值或存储字段中检索它。 从功能的角度来看,这是完全相同的,但您的选择可能会影响查询的执行时间。

STORED FIELDS,DOCVALUES AND ELASTICSEARCH_SOURCE INTERNAL REPRESENTATION

在本节中,我只想对存储字段、_source 字段和文档值的内部结构进行简要概述,以便有一些工具来理解使用这些方法进行字段检索的性能期望是什么。

STORED FIELDS INTERNALS

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

在这里插入图片描述

以上图为例。 要访问文档 x 的 field3,我们必须访问文档 x 的行并跳过 field3 之前存储的所有字段。 跳过字段需要获取其长度。 跳过字段并不像读取字段那么昂贵,但此操作并不是免费的。

DOCVALUES INTERNALS

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

ELASTICSEARCH _SOURCE FIELD INTERNALS

_source 呢? 嗯,如上所述,源是一个大字段,其中包含一个 JSON,其中包含索引时提供给 Elasticsearch 的所有输入。 但是,这个字段是如何存储的呢? 毫不奇怪,Elasticsearch 利用了 Lucene 已经实现和提供的机制:存储字段。 特别是,_source 字段是该行中第一个存储的字段。

在这里插入图片描述

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

Benchmarking

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

文档和查询集合取自此处。 我使用真实的集合来模拟现实场景。

执行详情:

  • CPU:AMD锐龙3600
  • 内存:32GB

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

这是基准测试的结果:
在这里插入图片描述

结果完全符合我们的预期。**如果每个文档需要几个字段,则建议使用文档值。**另一方面,当我们想要返回整个文档时,_source字段是最好的字段,而存储字段的使用是其他两个字段之间的完美折衷。

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

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

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


http://www.ppmy.cn/server/37484.html

相关文章

IT项目管理【太原理工大学】前置知识点精简总结

根据上次考试以及其他方向考试的经验,这届考试可能偏向出题更灵活,能死记硬背或套公式的题减少,多做准备呀各位大三苦逼人,挂了补考还得回来补考凸^-^凸共勉 (另外,别作弊,今天人工智能考试逮住…

【Linux】基础知识

常识 Linux命令行操作效率远大于图形界面,so… Linux终端打开时,默认以用户的home目录为当前工作目录 命令形式:command [-options] [parameter]; 多个参数同时使用时: ls -l -a; ls -la; ls -al; 多个参数同时使用三…

生信技能45 - 基于docker容器运行生信软件

1. 获取docker镜像 以运行xhmm CNV分析软件为例。 # 搜索仓库镜像 sudo docker search xhmm# 拉取镜像 sudo docker pull ksarathbabu/xhmm_v1.0# 启动镜像,非后台 sudo docker run -it ksarathbabu/xhmm_v1.0 /bin/bash # -i: 交互式操作。 # -t: 终端。 # ksarathbabu/xhmm…

IOT-9608I-L ADC端口的使用(连续采样ADC值)

目录 概述 1 硬件介绍 1.1 认识硬件 1.2 引脚信号定义 2 软件功能实现 2.1 查看iio:device0下的接口信息 2.2 实现连续采样ADC 2.2.1 功能描述 2.2.2 代码实现 2.2.3 详细代码 3 测试 概述 本文主要讲述IOT-9608I-L ADC端口的使用方便,其内容包括板卡上的…

我用 GitHub 9.8k 的 Go 语言 2D 游戏引擎写了个游戏

前言 hi,大家好,这里是白泽。今天给大家分享一个 GitHub 🌟9.8k 的 Go 语言 2D 游戏引擎。 https://github.com/hajimehoshi/ebiten 引擎的贡献者依旧在积极维护,是一个兼具学习 & 娱乐的项目! 为此我也用这个…

LY/T 3131-2019 木质拼花地板检测

木质拼花地板是指通过单元设计,组拼成具有特定图案的木质地板,按照材料组分分为实木拼花地板,实木复合拼花地板和浸渍纸层压拼花地板。 LY/T 3131-2019 实木拼花地板测试项目 测试项目 测试标准 含水率 GB/T 15036.2 漆膜附着力 GB/T 1…

Linux——mysql运维篇

回顾基本语句: 数据定义语言 ( DDL ) 。这类语言用于定义和修改数据库的结构,包括创建、删除和修改数据库、表、视图和索引等对象。主要的语句关键字包括 CREATE 、 DROP 、 ALTER 、 RENAME 、 TRUNCATE 等。 create database 数据库 &…

08-MVC处理流程

当浏览器发送一个http://127.0.0.1:8080/hello到达服务器后, 其处理流程如下: 服务器提供了一个DispatcherServlet, 继承自HttpServlet提供了标准的servlet技术. 路径: 默认映射路径为: / , 即会匹配所有请求路径, 可作为请求的统一入口. 也被称为前控制器. jsp不会匹配到Disp…