深入解析Elasticsearch的内部数据结构和机制:行存储、列存储与倒排索引之列存(二)

本文涉及的产品
Elasticsearch Serverless通用抵扣包,测试体验金 200元
简介: 深入解析Elasticsearch的内部数据结构和机制:行存储、列存储与倒排索引之列存(二)

一、什么是 Doc Values

Doc Values 是 Elasticsearch 中的一个内部数据结构,用于在字段级别存储排序和聚合所需的数据。与传统的行存储(将文档的每个字段值作为文档的一部分存储)不同,Doc Values 采用列式存储,这意味着它们按字段组织数据,而不是按文档。这种结构优化了读取性能,特别是当执行排序、聚合或脚本计算等操作时。

二、为什么需要Doc Values

在Elasticsearch中,排序和聚合操作对于处理和分析大量数据至关重要。然而,传统的倒排索引,尽管在全文检索时表现出色,但在执行这些操作时却显得力不从心。这是因为倒排索引是为快速查找包含特定词项的文档而设计的,而不是为收集特定文档集中的所有词项而优化的。

当我们对某个字段进行排序或聚合时,Elasticsearch需要访问每个匹配到的文档,以获取该字段的值。例如,考虑一个倒排索引,其中列出了不同词项及其所在的文档:

Term      | Doc_1 | Doc_2 | Doc_3  
------------------------------------  
brown     |   X   |   X   |  
dog       |   X   |       |   X

在这个结构中,快速找到包含“brown”的文档(Doc_1和Doc_2)是很容易的,因为倒排索引直接映射了词项到文档的关系。但是,如果我们想进一步分析这些文档,比如找出这些文档中所有唯一的词项,以便进行聚合,倒排索引就不那么高效了。


问题在于,为了使用倒排索引收集Doc_1和Doc_2中的所有词项,我们必须遍历索引中的每个词项,检查它是否属于这两个文档。这个过程随着词项和文档数量的增加而变得越来越慢,因为每次检查都需要在倒排列表中进行查找。


为了解决这个问题,Elasticsearch引入了Doc Values。Doc Values是一种列式的数据结构,它存储了每个文档字段值的完整、排序好的列表。与倒排索引不同,Doc Values不是将词项映射到文档,而是将文档映射到它们所包含的词项。这种结构使得按文档收集字段值变得非常高效。

以下是Doc Values如何表示数据的一个示例:

Doc      | Terms  
-----------------------------------------------------------------  
Doc_1    | brown, dog, fox, jumped, lazy, over, quick, the  
Doc_2    | brown, dogs, foxes, in, lazy, leap, over, quick, summer

在这个Doc Values结构中,每个文档都有一个与之直接关联的词项列表。因此,当需要收集Doc_1和Doc_2中所有唯一的词项时,我们只需直接访问这两个文档的词项列表,并执行集合的并集操作。这比使用倒排索引要快得多,因为无需遍历整个索引来收集特定文档的词项。

三、Doc Values 的工作原理

在 Elasticsearch 中,当索引一个文档时,除了将字段值存储在倒排索引中以支持全文搜索外,还会为需要排序或聚合的字段生成 Doc Values。这些 Doc Values 是字段值的压缩、列式表示,它们与倒排索引分开存储,并且针对快速、随机访问进行了优化。


Doc Values 的关键优势在于它们能够直接提供字段值,而无需重新解析存储的原始 JSON 文档(通常存储在 _source 字段中)。这是因为 Doc Values 是在索引时预先计算和存储的,因此它们可以非常快速地加载到内存中,并直接用于排序和聚合操作。以下是 Doc Values 的工作原理的详细解释:


数据生成与存储

当文档被索引到 Elasticsearch 时,除了生成倒排索引外,还会为文档的每个字段生成 Doc Values。这些 Doc Values 是字段值的列式存储,按文档顺序排列。

对于不需要进行全文检索的字段(如数字、日期或枚举类型),Doc Values 通常是这些字段值的直接存储形式。而对于需要进行全文检索的文本字段,Doc Values 可能会存储该字段的一个或多个分词结果。

内存与磁盘使用:

Doc Values 通常被序列化到磁盘上,以节省 JVM 堆内存的使用。由于它们是按列存储的,因此可以高效地加载到操作系统的文件系统缓存中(OS cache)。

当执行排序或聚合操作时,Elasticsearch 会尽可能地从 OS cache 中读取 Doc Values,从而减少对磁盘的直接 I/O 操作,提高性能。

查询过程:

当执行排序或聚合查询时,Elasticsearch 需要收集特定文档集中的字段值。使用 Doc Values,它可以直接访问这些文档的字段值列表,而无需遍历整个倒排索引。

Doc Values 的列式存储结构使得对这些值的操作(如排序、去重或聚合计算)非常高效,因为它们已经按文档顺序排列好了。

性能优化:

由于 Doc Values 是为快速读取而设计的,它们通常比从倒排索引中收集字段值要快得多。这是因为倒排索引是为快速查找文档而优化的,而不是为收集字段值而优化的。

Elasticsearch 还利用 Doc Values 来执行某些类型的过滤操作,如地理位置过滤,因为这些操作需要快速访问文档的字段值。

与倒排索引的关系:

Doc Values 并不是要替代倒排索引,而是作为其补充。倒排索引仍然用于全文检索和快速查找包含特定词项的文档。

Doc Values 和倒排索引一起工作,使得 Elasticsearch 能够在处理大量数据时提供高效的检索、排序和聚合功能。

通过了解 Doc Values 的工作原理,可以更好地理解 Elasticsearch 如何优化排序和聚合操作,并在实际应用中更有效地使用这些功能。

四、Doc Values 的类型及存储

es 支持多种类型的 Doc Values,包括数字、日期、IP 地址和二进制等。每种类型都有其特定的编码方式,以优化存储空间和查询性能。例如,数字类型的 Doc Values 可能会使用高效的压缩算法来减少存储空间,而日期类型的 Doc Values 则可能会存储为可快速比较的长整型时间戳。


4.1 持久化(Persistence)

Doc Values 是在索引文档时与倒排索引一同生成。Doc Values 基于每个段(per-segment)且是不可变的,这意味着一旦创建,它们就不会再改变。为了高效地存储和访问这些数据,Doc Values 会被序列化并持久化到磁盘上。


这样做的好处是可以充分利用操作系统的内存,而不是仅仅局限于 JVM 的 Heap 内存。当工作集(working set)远小于系统的可用内存时,系统会自动将 Doc Values 加载到内存中,使其读写操作非常快速。然而,当工作集远大于可用内存时,操作系统会根据需要将 Doc Values 从磁盘读取到内存中,或者将其写入磁盘。这种方式确保了 Doc Values 的大小不再受到服务器内存的限制,同时也避免了因为 JVM Heap 内存不足而导致的程序崩溃问题。


然而,需要注意的是,当工作集所需的内存空间非常大时,Doc Values 可能会被操作系统从内存中置换出去,这可能会导致访问速度的降低。


4.2 压缩(Compression)

Doc Values 的列式存储结构非常适合进行压缩,尤其是数字类型的字段。这种压缩不仅可以减少磁盘空间的使用,还可以提高数据的访问速度。Doc Values 在压缩过程中会使用多种策略,例如:


如果所有数值都各不相同(或缺失),它会设置一个标记并记录这些值。

如果这些值小于 256,它将使用一个简单的编码表。

如果这些值大于 256,它会检测是否存在一个最大公约数,这有助于进一步压缩数据。例如,如果所有数字都是 100 的倍数,那么可以通过除以 100 来减小数值的大小,从而减少存储所需的位数。

如果没有最大公约数,它会从最小的数值开始,统一计算偏移量进行编码。

对于字符串类型的字段,Doc Values 也可以通过顺序表对字符串进行数字编码,然后再对数字类型构建 Doc Values。这种方式间接地支持了字符串类型的压缩。

综上所述,Doc Values 的持久化机制确保了其可以灵活地处理不同大小的工作集,而压缩机制则有助于减少存储空间的占用并提高数据访问的效率。这些特性共同使得 Doc Values 成为 Elasticsearch 中优化排序和聚合操作性能的关键组件。

五、使用 Doc Values

Doc Values 默认对所有非分词字段生效,因为分词字段会产生大量 tokens,而 Doc Values 对其效果有限。如果确定不需要对某个字段进行聚合、排序或脚本操作,可以选择关闭该字段的 Doc Values,以节省磁盘空间并提高索引速度。

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "session_id": {
          "type":       "string",
          "index":      "not_analyzed",
          "doc_values": false
        }
      }
    }
  }
}

设置doc_values: false,这个字段将不再支持据聚合、排序和脚本执行(Script);

同时也可以对倒排索引做类似的配置:

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "customer_token": {
          "type":       "string",
          "index":      "not_analyzed",
          "doc_values": true,
          "index": "no"
        }
      }
    }
  }
}

这个可以支持聚合,但不支持查询,因为不会对这个字段生成倒排索引。

结论

Doc Values 是 Elasticsearch 性能优化的关键组成部分,它们通过预先计算和存储字段值,以及采用列式存储结构,大大提高了排序和聚合等查询操作的性能。对于需要处理大量数据和复杂查询的 Elasticsearch 集群来说,理解和优化 Doc Values 的使用至关重要。

相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。  
相关文章
|
10月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
265 2
|
11月前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
130 3
|
8月前
|
机器学习/深度学习 自然语言处理 搜索推荐
自注意力机制全解析:从原理到计算细节,一文尽览!
自注意力机制(Self-Attention)最早可追溯至20世纪70年代的神经网络研究,但直到2017年Google Brain团队提出Transformer架构后才广泛应用于深度学习。它通过计算序列内部元素间的相关性,捕捉复杂依赖关系,并支持并行化训练,显著提升了处理长文本和序列数据的能力。相比传统的RNN、LSTM和GRU,自注意力机制在自然语言处理(NLP)、计算机视觉、语音识别及推荐系统等领域展现出卓越性能。其核心步骤包括生成查询(Q)、键(K)和值(V)向量,计算缩放点积注意力得分,应用Softmax归一化,以及加权求和生成输出。自注意力机制提高了模型的表达能力,带来了更精准的服务。
10259 46
|
8月前
|
存储 人工智能 NoSQL
Tablestore深度解析:面向AI场景的结构化数据存储最佳实践
《Tablestore深度解析:面向AI场景的结构化数据存储最佳实践》由阿里云专家团队分享,涵盖Tablestore十年发展历程、AI时代多模态数据存储需求、VCU模式优化、向量检索发布及客户最佳实践等内容。Tablestore支持大规模在线数据存储,提供高性价比、高性能和高可用性,特别针对AI场景进行优化,满足结构化与非结构化数据的统一存储和高效检索需求。通过多元化索引和Serverless弹性VCU模式,助力企业实现低成本、灵活扩展的数据管理方案。
394 12
|
8月前
|
存储 分布式计算 Hadoop
基于Java的Hadoop文件处理系统:高效分布式数据解析与存储
本文介绍了如何借鉴Hadoop的设计思想,使用Java实现其核心功能MapReduce,解决海量数据处理问题。通过类比图书馆管理系统,详细解释了Hadoop的两大组件:HDFS(分布式文件系统)和MapReduce(分布式计算模型)。具体实现了单词统计任务,并扩展支持CSV和JSON格式的数据解析。为了提升性能,引入了Combiner减少中间数据传输,以及自定义Partitioner解决数据倾斜问题。最后总结了Hadoop在大数据处理中的重要性,鼓励Java开发者学习Hadoop以拓展技术边界。
270 7
|
8月前
|
存储 算法 C++
【C++数据结构——图】图的邻接矩阵和邻接表的存储(头歌实践教学平台习题)【合集】
本任务要求编写程序实现图的邻接矩阵和邻接表的存储。需掌握带权有向图、图的邻接矩阵及邻接表的概念。邻接矩阵用于表示顶点间的连接关系,邻接表则通过链表结构存储图信息。测试输入为图的顶点数、边数及邻接矩阵,预期输出为Prim算法求解结果。通关代码提供了完整的C++实现,包括输入、构建和打印邻接矩阵与邻接表的功能。
265 10
|
10月前
|
存储 缓存 监控
后端开发中的缓存机制:深度解析与最佳实践####
本文深入探讨了后端开发中不可或缺的一环——缓存机制,旨在为读者提供一份详尽的指南,涵盖缓存的基本原理、常见类型(如内存缓存、磁盘缓存、分布式缓存等)、主流技术选型(Redis、Memcached、Ehcache等),以及在实际项目中如何根据业务需求设计并实施高效的缓存策略。不同于常规摘要的概述性质,本摘要直接点明文章将围绕“深度解析”与“最佳实践”两大核心展开,既适合初学者构建基础认知框架,也为有经验的开发者提供优化建议与实战技巧。 ####
|
10月前
|
缓存 NoSQL Java
千万级电商线上无阻塞双buffer缓冲优化ID生成机制深度解析
【11月更文挑战第30天】在千万级电商系统中,ID生成机制是核心基础设施之一。一个高效、可靠的ID生成系统对于保障系统的稳定性和性能至关重要。本文将深入探讨一种在千万级电商线上广泛应用的ID生成机制——无阻塞双buffer缓冲优化方案。本文从概述、功能点、背景、业务点、底层原理等多个维度进行解析,并通过Java语言实现多个示例,指出各自实践的优缺点。希望给需要的同学提供一些参考。
177 8
|
9月前
|
PHP 开发者 UED
PHP中的异常处理机制解析####
本文深入探讨了PHP中的异常处理机制,通过实例解析try-catch语句的用法,并对比传统错误处理方式,揭示其在提升代码健壮性与可维护性方面的优势。文章还简要介绍了自定义异常类的创建及其应用场景,为开发者提供实用的技术参考。 ####
|
9月前
|
Java 数据库连接 开发者
Java中的异常处理机制:深入解析与最佳实践####
本文旨在为Java开发者提供一份关于异常处理机制的全面指南,从基础概念到高级技巧,涵盖try-catch结构、自定义异常、异常链分析以及最佳实践策略。不同于传统的摘要概述,本文将以一个实际项目案例为线索,逐步揭示如何高效地管理运行时错误,提升代码的健壮性和可维护性。通过对比常见误区与优化方案,读者将获得编写更加健壮Java应用程序的实用知识。 --- ####

推荐镜像

更多
  • DNS