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

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 深入解析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 的使用至关重要。

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
目录
打赏
0
0
0
0
39
分享
相关文章
|
4月前
|
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
62 3
C 408—《数据结构》图、查找、排序专题考点(含解析)
408考研——《数据结构》图,查找和排序专题考点选择题汇总(含解析)。
69 29
C 408—《数据结构》易错考点200题(含解析)
408考研——《数据结构》精选易错考点200题(含解析)。
92 27
Tablestore深度解析:面向AI场景的结构化数据存储最佳实践
《Tablestore深度解析:面向AI场景的结构化数据存储最佳实践》由阿里云专家团队分享,涵盖Tablestore十年发展历程、AI时代多模态数据存储需求、VCU模式优化、向量检索发布及客户最佳实践等内容。Tablestore支持大规模在线数据存储,提供高性价比、高性能和高可用性,特别针对AI场景进行优化,满足结构化与非结构化数据的统一存储和高效检索需求。通过多元化索引和Serverless弹性VCU模式,助力企业实现低成本、灵活扩展的数据管理方案。
68 12
基于Java的Hadoop文件处理系统:高效分布式数据解析与存储
本文介绍了如何借鉴Hadoop的设计思想,使用Java实现其核心功能MapReduce,解决海量数据处理问题。通过类比图书馆管理系统,详细解释了Hadoop的两大组件:HDFS(分布式文件系统)和MapReduce(分布式计算模型)。具体实现了单词统计任务,并扩展支持CSV和JSON格式的数据解析。为了提升性能,引入了Combiner减少中间数据传输,以及自定义Partitioner解决数据倾斜问题。最后总结了Hadoop在大数据处理中的重要性,鼓励Java开发者学习Hadoop以拓展技术边界。
50 7
|
1月前
|
【C++数据结构——图】图的邻接矩阵和邻接表的存储(头歌实践教学平台习题)【合集】
本任务要求编写程序实现图的邻接矩阵和邻接表的存储。需掌握带权有向图、图的邻接矩阵及邻接表的概念。邻接矩阵用于表示顶点间的连接关系,邻接表则通过链表结构存储图信息。测试输入为图的顶点数、边数及邻接矩阵,预期输出为Prim算法求解结果。通关代码提供了完整的C++实现,包括输入、构建和打印邻接矩阵与邻接表的功能。
49 10
PyPI 存储库中的 JarkaStealer:深入解析与防范措施
PyPI 存储库中的 JarkaStealer:深入解析与防范措施
45 2
Redis数据结构:List类型全面解析
Redis数据结构——List类型全面解析:存储多个有序的字符串,列表中每个字符串成为元素 Eelement,最多可以存储 2^32-1 个元素。可对列表两端插入(push)和弹出(pop)、获取指定范围的元素列表等,常见命令。 底层数据结构:3.2版本之前,底层采用**压缩链表ZipList**和**双向链表LinkedList**;3.2版本之后,底层数据结构为**快速链表QuickList** 列表是一种比较灵活的数据结构,可以充当栈、队列、阻塞队列,在实际开发中有很多应用场景。
除了 HashMap,还有哪些数据结构可以实现键值对存储?
【10月更文挑战第11天】 除了`HashMap`,其他常见支持键值对存储的数据结构包括:`TreeMap`(基于红黑树,键有序)、`LinkedHashMap`(保留插入顺序)、`HashTable`(线程安全)、`B-Tree`和`B+Tree`(高效存储大量数据)、`SkipList`(通过跳跃指针提高查找效率)及`UnorderedMap`(类似`HashMap`)。选择合适的数据结构需根据排序、并发、存储和查找性能等需求。
百亿级存储架构: ElasticSearch+HBase 海量存储架构与实现
本文介绍了百亿级数据存储架构的设计与实现,重点探讨了ElasticSearch和HBase的结合使用。通过ElasticSearch实现快速检索,HBase实现海量数据存储,解决了大规模数据的高效存储与查询问题。文章详细讲解了数据统一接入、元数据管理、数据一致性及平台监控等关键模块的设计思路和技术细节,帮助读者理解和掌握构建高性能数据存储系统的方法。
百亿级存储架构: ElasticSearch+HBase 海量存储架构与实现

热门文章

最新文章

推荐镜像

更多
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等