学习
实践
活动
专区
工具
TVP
写文章
专栏首页铭毅天下Elasticsearch 内部数据结构深度解读

Elasticsearch 内部数据结构深度解读

题记

最近知识星球里几个问题都问到了 doc values、store field、fielddata 等的概念。

问题1:”群主有介绍 doc value, field data, store fields 比较好的文章么?一直感觉有点模糊“ 问题2:“请教下星主关于ES存储相关的问题, 一个文档有如下几个地方可能会存储:

  • 倒排索引。
  • Source 字段。
  • store 存储(如果开启)
  • doc_values。

不知道我理解的是否正确? 如果这几个地方都存储, 那是不是可以理解为数据大致会膨胀了4倍? 死磕 Elasticsearch 知识星球(http://t.cn/RmwM3N9)

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

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

1、数据存储认知前提

正如 Elastic 官方文档所说:

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

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

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

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

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

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

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

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

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

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

数据类型

数据结构

text/keyword

倒排索引

数字/地理位置

BKD树

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

1、Inverted Index 倒排索引

1.1 倒排索引定义

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

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

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

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

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 被定义为:“正排索引”。

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 后,如下操作将不可用:

  1. update, update_by_query 和 reindex API
  2. 高亮操作

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

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 !

参考:

  1. https://t.zsxq.com/Baq3nmE
  2. https://t.zsxq.com/meAyrzN
  3. https://t.zsxq.com/IaunyrZ
  4. https://t.zsxq.com/AIYJiE6
  5. https://medium.com/datadriveninvestor/elastic-search-what-is-inside-5d61f1a681df
  6. http://alexander.holbreich.org/elasticsearch-datastructures/
  7. Elastic 官方文档
文章分享自微信公众号:
铭毅天下

本文参与 腾讯云自媒体分享计划 ,欢迎热爱写作的你一起参与!

作者:铭毅天下
原始发表时间:2020-10-08
如有侵权,请联系 cloudcommunity@tencent.com 删除。
登录 后参与评论
0 条评论

相关文章

  • 深度解读:2021 海外企业「内部系统」现状

    低代码公司 Retool 于去年发布了一份基于 650 名开发者/技术负责人的名为「The state of internal tools in 2021」的调...

    码匠Majiang
  • 干货 | 全方位深度解读 Elasticsearch 分页查询

    第一:非常适合小型数据集或者大数据集返回 Top N(N <= 10000)结果集的业务场景。

    铭毅天下
  • Java 内部新闻第二期深度解读

    这是由 Java 官方发布,Oracle JDK 研发 Nipafx 制作的节目,包含 JDK 近期的研发进展和新特性展望和使用,这里加上个人译制的字幕搬运而来...

    干货满满张哈希
  • Elasticsearch 缓存深入详解

    Elasticsearch 查询的响应需要占用 CPU、内存资源,在复杂业务场景,会出现慢查询,需要花费大量的时间。

    铭毅天下
  • 2天,我把 Redis 学废了!

    要说在近几年的面试里,考察难度只增不减的,Redis可谓是当仁不让! 而往前倒推几年,最人气的NoSQL数据库还是MongoDB,同一年发布的Redis甚至排不...

    孙玄@奈学教育
  • 阿里二面被问Redis主从复制和集群,14:03进去的,14:08就出来了…

    要说在近几年的面试里,考察难度只增不减的,Redis可谓是当仁不让! 而往前倒推几年,最人气的NoSQL数据库还是MongoDB,同一年发布的Redis甚至排不...

    java思维导图
  • 阿里二面被问 Redis 主从复制和集群,14:03 进去的,14:08 就出来了…

    要说在近几年的面试里,考察难度只增不减的,Redis 可谓是当仁不让! 而往前倒推几年,最人气的 NoSQL 数据库还是 MongoDB,同一年发布的 Redi...

    崔庆才
  • 实战 | Elasticsearch自定义评分的N种方法

    比如:同样输入“锤子”,工匠期望的是钉子对应的“锤子”,老罗的粉丝期望的是“锤子科技”、“锤子便签”、“锤子手机”等。

    铭毅天下
  • 严选 | ELK Stack 选书指南

    非针对ELK Stack的书,是搜索引擎原理的书,Elasticsearch也是开源搜索引擎的一种,原理通用。

    铭毅天下
  • Elastic Meetup2021深圳站回顾

    导语 |  一波未平一波又起的疫情对大家的生活、工作造成了一定影响。在信息化飞速发展的今天,小伙伴们技术交流的方式也变得多样化。2021年8月21日下午,ES中...

    腾讯云开发者
  • 又一里程碑!阿里首推Java技术成长笔记,业内评级“钻石级”

    根据数据表明,阿里巴巴已经连续3年获评最受欢迎的中国互联网公司,实际上阿里巴巴无论在科技创新力还是社会创造价值这几个方面,都是具有一定代表里的。在行业内,很多互...

    愿天堂没有BUG
  • 腾讯云 x Elasticsearch 携手三周年有奖征文大赛

    在腾讯云 与 Elasticsearch 合作三周年之际,双方共同发起《腾讯云 x Elasticsearch 携手三周年有奖征文大赛》,欢迎大家畅所欲言!可从...

    腾讯云大数据
  • 重庆java培训机构哪个好_java培训班

    说到CAS(CompareAndSwap),不得不先说一说悲观锁和乐观锁,因为CAS是乐观锁思想的一种实现。

    全栈程序员站长
  • Searching with Deep Learning 深度学习的搜索应用

    目录: 一、Fast Nearest Neighbours 二、Elasticsearch 插件 三、集成工作 四、结论

    2020labs小助手
  • Searching with Deep Learning 深度学习的搜索应用

    最近我在帮一个数据科学家同事工程化一个基于深度学习模型的搜索系统。他们的项目是关于在文档嵌入应用深度学习模型,然后使用嵌入向量到我们的搜索系统中来查找相似文档。

    杨振涛
  • Searching with Deep Learning 深度学习的搜索应用

    最近我在帮一个数据科学家同事工程化一个基于深度学习模型的搜索系统。他们的项目是关于在文档嵌入应用深度学习模型,然后使用嵌入向量到我们的搜索系统中来查找相似文档。

    杨振涛
  • Elastic Meetup 2021 深圳站回顾

    一波未平一波又起的疫情对大家的生活、工作造成了一定影响。在信息化飞速发展的今天,小伙伴们技术交流的方式也变得多样化。2021年8月21日下午,ES 中文社区联合...

    黄华

扫码关注腾讯云开发者

领取腾讯云代金券