Elasticsearch 内部数据结构深度解读

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 近知识星球里几个问题都问到了 doc values、store field、fielddata 等的概念。问题1:”群主有介绍 doc value, field data, store fields 比较好的文章么?一直感觉有点模糊“问题2:“请教下星主关于ES存储相关的问题, 一个文档有如下几个地方可能会存储:倒排索引。Source 字段。store 存储(如果开启)doc_values。不知道我理解的是否正确?如果这几个地方都存储, 那是不是可以理解为数据大致会膨胀了4倍?死磕 Elasticsearch 知识星球(http://t.cn/RmwM3N9

image.png

链接

非常有必要好好梳理一下,于是就有了这篇文章。


Elasticsearch 数据结构的理解和合理使用,对深入理解 Elasticsearch大有裨益!


1、数据存储认知前提

正如 Elastic 官方文档所说:


Elasticsearch 特点之一是:分布式文档存储。


Elasticsearch不会将信息存储为类似列数据库的行(row),而是存储为已序列化为JSON文档的复杂数据结构。


当集群中有多个Elasticsearch节点时,存储的文档会分布在整个集群中,并且可以从任何节点立即访问。


存储文档后,将在1秒钟内(默认刷新频率为1s)几乎实时地对其进行索引和完全搜索。


如何做到快速索引和全文检索的呢?


Elasticsearch使用倒排索引的数据结构,该结构支持非常快速的全文本搜索。


倒排索引列出了出现在任何文档中的每个唯一单词,并标识了每个单词出现的所有文档。


索引可以认为是文档的优化集合,每个文档都是字段的集合,这些字段是包含数据的键值对。

默认情况下,Elasticsearch 对每个字段中的所有数据建立索引,并且每个索引字段都具有专用的优化数据结构。


例如,文本字段存储在倒排索引中,数字字段和地理字段存储在BKD树中。



数据类型 数据结构

text/keyword 倒排索引

数字/地理位置 BKD树

不同字段具有属于自己字段类型的特定优化数据结构,并具备快速响应返回搜索结果的能力使得 Elasticsearch 搜索飞快!


1、Inverted Index 倒排索引

1.1 倒排索引定义

面对海量内容,如何快速的找到包含用户查询词的内容,倒排索引扮演了关键角色。


倒排索引是单词到文档映射关系的最佳实现形式。


下图是:书的末页的索引结构,展示了核心关键词与书页码的对应关系。

image.png

试想一下,没有这个索引页,根据关键词从全书查找有多慢,就能直观体会出索引的妙处!


1.2 倒排索引示例

拿官方文档的示例:


假设我们有两个文档,每个文档的 content 域包含如下内容:


- 1、The quick brown fox jumped over the lazy dog

- 2、Quick brown foxes leap over lazy dogs in summer

对索引编制索引会受到标记化和标准化的处理analysis。


数据索引化制约因素:分词器 analyzer 的选型。


倒排索引(基于 默认Standard 标准分词器分词)如下所示:



Term Doc_1 Doc_2

Quick   X

The X  

brown X X

dog X  

dogs   X

fox X  

foxes   X

in   X

jumped X  

lazy X X

leap   X

over X X

quick X  

summer   X

the X  

如上所示,对于文档中的每个词,都包含了其所在文档的列表。


1.3 倒排索引特点

在索引时创建


序列化到磁盘


全文搜索非常快


不适合做排序


默认开启


1.4 倒排索引适用场景

查询


全文检索


2、Doc Values 正排索引

2.1 Doc Values 定义

在 Elasticsearch 中,Doc Values 就是一种列式存储结构,默认情况下每个字段的 Doc Values 都是激活的(除了 text 类型),Doc Values 是在索引时创建的,当字段索引时,Elasticsearch 为了能够快速检索,会把字段的值加入倒排索引中,同时它也会存储该字段的 Doc Values。


区别于倒排索引的定义,Doc Values 被定义为:“正排索引”。

image.png

2.2 Doc Values 示例

仍然 以 1.2 文档为例,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 values 将文档映射到它们包含的词项。


2.3 Doc Values 特点

在索引时创建


序列化到磁盘


适合排序操作


将单个字段的所有值一起存储在单个数据列中


默认情况下,除text之外的所有字段类型均启用 Doc Values。


2.4 Doc Values 适用场景

Elasticsearch 中的 Doc Values 常被应用到以下场景:


对一个字段进行排序


对一个字段进行聚合


某些过滤,比如地理位置过滤


某些与字段相关的脚本计算


注意:


因为文档值被序列化到磁盘,我们可以依靠操作系统的帮助来快速访问。


当 工作集(working set) 远小于节点的可用内存,系统会自动将所有的文档值保存在内存中,使得其读写十分高速;


当其远大于可用内存,操作系统会自动把 Doc Values 加载到系统的页缓存中,从而避免了 jvm 堆内存溢出异常。


2. 5 Doc Values 使用注意事项

对于不需要:排序、聚合、脚本计算、地理位置过滤的业务场景,可以考虑禁用:Doc Values,以节约存储。


PUT my_index

{

 "mappings": {

     "properties": {

       "title": {

         "type": "keyword",

         "doc_values": false

       }

   }

 }

}

3、fielddata

3.1 fielddata 定义

如前第1、2小结所述:


搜索需要回答“哪个文档包含此词?”的问题。借助:倒排索引实现。


排序和汇总则需要回答一个不同的问题:“此字段对本文档的价值是什么?” 。借助:正排索引实现。


text 类型字段是不支持 Doc Values正排索引的,text字段使用是:查询时创建的基于的内存数据结构(query-time in-memory data structure) fielddata。


fielddata 将 text 字段用于聚合、排序或在脚本中使用时,将按需构建此数据结构。


实现机理:它是通过从磁盘读取每个段的整个反向索引,反转词项↔︎文档关系并将结果存储在JVM堆中的内存中来构建的。


3.2 fielddata 示例

严格意义讲,2.2 的示例,放到这里会更合适。


DELETE test_001

PUT test_001

{

 "mappings": {

   "properties": {

     "body":{

       "type":"text",

       "analyzer": "standard",

       "fielddata": true

     }

   }

 }

}

POST test_001/_bulk

{"index":{"_id":1}}

{"body":"The quick brown fox jumped over the lazy dog"}

{"index":{"_id":2}}

{"body":"Quick brown foxes leap over lazy dogs in summer"}

GET test_001/_search

{

 "size": 0,

 "query": {

   "match": {

     "body": "brown"

   }

 },

 "aggs": {

   "popular_terms": {

     "terms": {

       "field": "body"

     }

   }

 }

}

3.3 fielddata 特点

适用于文档之类的操作


但仅适用于 text 文本字段类型


在查询时创建


内存中数据结构


没有序列化到磁盘


默认情况下被禁用(构建它们很昂贵,并且在堆中预置)


3.4 fielddata 适用场景

全文统计词频


全文生成词云


text类型:聚合、排序、脚本计算


3.5 fielddata 使用注意事项

在启用字段数据之前,请考虑为什么将文本字段用于聚合、排序或在脚本中使用。


启用 fielddata 通常没有任何意义,因为它非常耗费内存资源。


仅仅是做全文搜索的应用,就不需要启用fielddata。


4、_source 字段解读

4.1 _source 定义

_source 字段包含在索引时间传递的原始JSON文档主体。


_source 字段本身未构建索引(因此不可搜索),但已存储该字段,以便在执行获取请求(如get或search)时可以将其返回。


4.2 _source 使用注意事项

第一:尽管非常方便,但是source字段确实会导致索引内的存储开销。因此,可以将其禁用。


PUT my-index-000001

{

 "mappings": {

   "_source": {

     "enabled": false

   }

 }

}

第二:禁用前要做好以下衡量 禁用 _source 后,如下操作将不可用:


update, update_by_query 和 reindex API


高亮操作


所以,要在存储空间、业务场景之间权衡利弊后选型。


5、store 字段解读

5.1 store 定义

默认情况下,对字段值进行索引以使其可搜索(第1节的 倒排索引),但不存储它们。


这意味着可以查询该字段,但是无法检索原始字段值。


通常这无关紧要。该字段值已经是_source字段的一部分,默认情况下已存储。


但,某些特殊场景下,如果你只想检索单个字段或几个字段的值,而不是整个_source的值,则可以使用源过滤来实现。


这个时候, store 就派上用场了。


5.2 store 示例

DELETE news-000001

PUT news-000001

{

 "mappings": {

   "_source": {

     "enabled": false

   },

   "properties": {

     "title": {

       "type": "text",

       "store": true

     },

     "date": {

       "type": "date",

       "store": true

     },

     "content": {

       "type": "text"

     }

   }

 }

}

PUT news-000001/_doc/1

{

 "title":   "Some short title",

 "date":    "2021-01-01",

 "content": "A very long content field..."

}

GET news-000001/_search

GET news-000001/_search

{

 "stored_fields": [ "title", "date" ]

}

5.3 store 适用场景

如 5.2 示例,在某些情况下,存储字段可能很有意义。例如,采集的新闻数据是:带有标题、日期和很大内容字段的文档,


则可能只想检索标题和日期,而不必从较大的_source字段中提取这些字段。


6、小结

回到文章开头的两个问题:


问题1:看完本文后,doc values , field data , store fields  就非常清晰了。


问题2:字段类型不一样,存储不一样。默认:倒排索引默认所有字段都启用,正排索引 Doc Values 非 text 类型默认启用, source (存储原始文档的 所有字段的 json 结构数据)和 store (存储指定字段的 json 数据) 的启用与否需要结合业务实际。假设:正排索引、倒排索引、_source 、store 都启用了,存储肯定会增加,但不是线性的 4倍。


对于不明白的问题,反复研读官方文档,拷贝到kibana Dev tool 去实践,直到弄明白为止。


文章尽量参考官方文档,尽管如此,难免表述纰漏,欢迎大家指正交流。


和你一起,死磕 Elasticsearch !


参考:


https://t.zsxq.com/Baq3nmE


https://t.zsxq.com/meAyrzN


https://t.zsxq.com/IaunyrZ


https://t.zsxq.com/AIYJiE6


https://medium.com/datadriveninvestor/elastic-search-what-is-inside-5d61f1a681df


http://alexander.holbreich.org/elasticsearch-datastructures/


Elastic 官方文档


推荐:


干货 | Elasticsearch 开发实战常用命令清单


你的 Elasticsearch 难题,官方文档早就有了答案......


干货 | Elasticsearch开发人员最佳实战指南


Elasticsearch 开发运维实战核心 Tips


干货 | 论Elasticsearch数据建模的重要性


干货 | Elasticsearch 索引设计实战指南


干货 | Elasticsearch多表关联设计指南

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
7月前
|
存储 自然语言处理 NoSQL
深入解析Elasticsearch的内部数据结构和机制:行存储、列存储与倒排索引之倒排索引(三)
深入解析Elasticsearch的内部数据结构和机制:行存储、列存储与倒排索引之倒排索引(三)
|
7月前
|
存储 自然语言处理 NoSQL
深入解析Elasticsearch的内部数据结构和机制:行存储、列存储与倒排索引之列存(二)
深入解析Elasticsearch的内部数据结构和机制:行存储、列存储与倒排索引之列存(二)
|
7月前
|
存储 JSON NoSQL
深入解析Elasticsearch的内部数据结构和机制:行存储、列存储与倒排索引之行存(一)
深入解析Elasticsearch的内部数据结构和机制:行存储、列存储与倒排索引之行存(一)
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
249 9
|
2月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
40 1
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
74 5
|
2月前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。
|
2月前
|
存储 JavaScript 前端开发
执行上下文和执行栈
执行上下文是JavaScript运行代码时的环境,每个执行上下文都有自己的变量对象、作用域链和this值。执行栈用于管理函数调用,每当调用一个函数,就会在栈中添加一个新的执行上下文。
|
2月前
|
存储
系统调用处理程序在内核栈中保存了哪些上下文信息?
【10月更文挑战第29天】系统调用处理程序在内核栈中保存的这些上下文信息对于保证系统调用的正确执行和用户程序的正常恢复至关重要。通过准确地保存和恢复这些信息,操作系统能够实现用户模式和内核模式之间的无缝切换,为用户程序提供稳定、可靠的系统服务。
55 4
|
3月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
57 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器