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

在当今的大数据时代,高效的数据检索和分析能力已成为许多应用程序的核心需求。Elasticsearch,作为一款强大的分布式搜索和分析引擎,正是为了满足这些需求而诞生的。它之所以能够在海量数据中实现毫秒级的搜索响应,以及灵活的数据分析,要归功于其内部精妙的数据结构和机制。本文将详细探讨Elasticsearch中的行存储(Stored Fields)、列存储(Doc Values)和倒排索引(Inverted Index)这三种关键组件,并解释它们是如何协同工作的。

1 什么是行存

在Lucene中索引文档时,原始字段信息经过分词、转换处理后形成倒排索引,而原始内容本身并不直接保留。因此,为了检索时能够获取到字段的原始值,我们需要依赖额外的数据结构。Lucene提供了两种解决方案:Stored Field和doc_values。

Stored Field的设计初衷就是为了存储那些未经分词的字段原始值。这样,在执行查询操作时,除了能够获取到文档ID之外,我们还能够方便地检索到这些原始字段信息。

es中每个文档都被视为一个JSON对象,包含多个字段。当文档被索引时,其原始数据或特定字段可以被存储在es中,以便后续能够检索到原始的字段值。这种存储方式类似于传统的行存储数据库,因为它存储了每个文档的所有字段。

然而,需要注意的是,es并不建议大量使用Stored Fields。这是因为存储原始字段值会增加磁盘使用量,并可能降低性能。相反,es更倾向于使用Doc Values和倒排索引来高效地检索和分析数据。因此,Stored Fields通常只用于存储那些需要在搜索结果中直接返回的字段。

2 使用场景

那么,什么时候应该使用Stored Fields呢?

  • 需要返回原始字段值:如果你的应用程序需要在搜索结果中返回文档的原始字段值,那么你应该将这些字段设置为Stored Fields。例如,你可能需要显示给用户文档的标题、描述或内容等字段。
  • 不支持Doc Values的字段类型:并非所有字段类型都支持Doc Values。对于那些不支持Doc Values的字段类型,如果你需要在搜索结果中返回这些字段的值,那么你需要将它们设置为Stored Fields。

3 如何使用

可以通过映射(Mapping)来定义哪些字段应该被存储为Stored Fields。映射是定义文档结构和字段属性的过程。

3.1 定义store字段
PUT order
{"mappings": {"_doc": {"properties": {"counter": {"type": "integer","store": false        //默认值就是false},"tags": {"type": "keyword","store": true      //修改值为true}}}}
}

我们创建了一个名为order的索引,并定义了两个字段:counter和tags。我们将tags字段的store属性设置为true,这意味着tags字段的值将被存储为Stored Fields。而counter字段的store属性设置为false,表示不存储该字段的值。

3.2 添加 document
PUT order/_doc/1
{"counter" : 1,"tags" : ["red"]
}
3.3 尝试带stored_fields参数去检索
GET twitter/_doc/1?stored_fields=tags,counter以上get操作的结果是:{"_index": "twitter","_type": "tweet","_id": "1","_version": 1,"found": true,"fields": {           //此时多了名称为fields的字段,并且没有了_source"tags": [          //tags的stroe属性设置为true,因此显示在结果中"red"]}
}

从 document 中获取的字段的值通常是array。
由于counter字段没有存储,当尝试获取stored_fields时get会将其忽略。

在Elasticsearch中,不论将字段的store属性设置为true还是false,这些字段都会被存储。但存储的方式有所不同:

  • 当store设置为false时(这是默认配置),字段值仅存储在文档的_source字段中。这意味着,字段值作为整个文档JSON结构体的一部分被保存。
  • 当store设置为true时,字段值不仅存储在_source字段中,还会被单独存储在一个与_source平级的独立字段中。这样,该字段就有了两份拷贝:一份在_source中,另一份在独立的字段中。

那么,在什么情况下需要将字段的store属性设置为true呢?通常有两种情况:

  • _source字段在索引的映射中被禁用(disabled)
    在这种情况下,如果某个字段没有被定义为store=true,那么该字段将不会出现在查询结果中。因此,为了确保能够在查询结果中访问这些字段,需要将其设置为store=true。
  • _source字段的内容非常大
    当文档包含大量数据时,例如一本书的内容,而查询时只需要访问其中的部分字段(如标题和日期),而不是整个_source字段,那么将这些字段设置为store=true可以提高查询效率。这样做可以避免在查询时解释整个_source字段,从而减少开销。当然,另一种选择是使用source filtering来减少网络开销,但将特定字段设置为store=true也是一种有效的优化方法。

4 行存储与_source字段

行存储中,占比最大的通常是_source字段,它负责保存文档的原始数据。在数据写入阶段,Elasticsearch会将整个文档的JSON结构体作为字符串存储在_source字段中。在查询时,我们可以通过_source字段检索到原始写入的完整JSON结构体。

在这里插入图片描述

{"_index": "order","_type": "_doc","_id": "1","_version": 1,"_seq_no": 0,"_primary_term": 1,"found": true,"_source": {      //默认查询数据,返回的属性字段都在_source中"user": "kimchy","post_date": "2009-11-15T14:12:12","message": "trying out Elasticsearch"}
}

_source字段:

  • _source字段的角色:在Elasticsearch中,每个索引的文档都有一个特殊的字段叫做_source。这个字段包含了文档的原始JSON表示。当你索引一个文档时,Elasticsearch会将这个文档的JSON形式存储为_source字段的内容。这意味着,无论你的文档包含什么字段(例如,标题、描述、日期等),它们都会被打包进这个_source字段中。
  • 存储与检索:由于_source字段存储了文档的完整原始数据,因此它通常是索引中最大的字段之一。当你执行一个检索操作时,Elasticsearch默认会返回匹配文档的_source字段,从而允许你访问到文档的原始数据。
  • 用途:拥有文档的原始数据非常有用,特别是在你需要重新构建文档的上下文时(例如,在搜索结果中显示文档的内容)。此外,许多Elasticsearch的功能,如高亮显示或字段提取,都依赖于_source字段的内容。

优化_source字段的使用:

  • 关闭_source:如果你确定不需要文档的原始数据,可以在索引的映射中关闭_source字段的存储。这样做可以节省存储空间并提高索引速度。然而,这样做有一个重要的限制:关闭_source字段后,你将无法使用update、update_by_query和reindex等API,因为这些操作需要访问文档的原始数据。
  • 包含/排除字段:另一种优化方法是选择性地包含或排除_source字段中的某些数据。例如,你可能只想存储文档的某些关键字段,而不是整个JSON结构体。这可以通过在索引文档时使用特定的参数或在映射中定义_source字段的包含/排除规则来实现。

注意事项:

  • 在决定关闭_source字段或修改其包含的内容之前,务必仔细考虑你的应用程序的需求。如果你在未来需要使用文档的原始数据,或者需要使用依赖于_source字段的Elasticsearch功能,那么关闭或修改_source字段可能会导致问题。
  • 尽管关闭_source字段可以节省存储空间,但这通常不是优化Elasticsearch性能的首选方法。在大多数情况下,通过优化查询、选择合适的分析器、合理设置映射和使用硬件资源等方式,可以获得更好的性能提升。

5 总结

行存储有几个重要的优点:

  • 完整性:由于_source字段存储了文档的完整原始数据,因此可以重新构建文档的上下文,这对于搜索结果展示、高亮显示等功能至关重要。
  • 灵活性:拥有文档的原始数据使得ES能够提供多种功能,如字段提取、动态映射更改等,这些功能都依赖于_source字段的内容。
  • 便于调试:对于开发者而言,能够直接访问文档的原始数据有助于调试和验证索引的正确性。

然而,行存储也有一些潜在的开销和限制:

  • 存储成本:由于每个文档的完整原始数据都被存储在索引中,这可能会增加存储空间的需求,尤其是对于大量文档或大型文档而言。
  • 写入性能:在写入大量文档时,将每个文档的完整JSON结构体存储到_source字段可能会对写入性能产生一定的影响。

在使用ES时,开发者需要根据具体的应用场景和需求来权衡行存储的利弊,并合理地配置和优化索引结构。例如,在某些场景下,可能只需要存储文档的部分字段而不是完整的JSON结构体,这可以通过在映射中关闭_source字段或只包含必要的字段来实现。然而,需要注意的是,关闭_source字段后将无法使用依赖于_source字段的ES功能,如更新、重新索引等。因此,在做出决策时需要仔细考虑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/254899.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker进阶篇-CIG重量级监控系统

一、简介 通过docker stats命令可以很方便的查看当前宿主机上所有容器的CPU、内存、网络流量等数 据,可以满足一些小型应用。 但是docker stats统计结果只能是当前宿主机的全部容器,数据资料是实时的,没有地方存储、 没有健康指标过线预警…

肯尼斯·里科《C和指针》第13章 高级指针话题(3)命令行参数

处理命令行参数是指向指针的指针的另一个用武之地。有些操作系统,包括UNIX和MS-DOS,让用户在命令行中编写参数来启动一个程序的执行。这些参数被传递给程序,程序按照它认为合适的任何方式对它们进行处理。 13.4.1 传递命令行参数 这些参数如何…

html5 audio video

DOMException: play() failed because the user didn‘t interact with the document first.-CSDN博客 不可用: 可用: Google Chrome Close AutoUpdate-CSDN博客

用HTML5实现灯笼效果

本文介绍了两种实现效果:一种使用画布(canvas)标签/元素,另一种不用画布(canvas)标签/元素主要使用CSS实现。 使用画布(canvas)标签/元素实现,下面,在画布上…

Compose | UI组件(十四) | Navigation-Data - 页面导航传递数据

文章目录 前言传参流程实例说明普通方式传值定义接受参数格式定义接受参数类型获取参数传入参数传参和接受参数效果图 结合 ViewModel 传递参数定义ViewModel在 navigation 定义 ViewModel 实例,并且传入 LoginScreen传入输入框中的值,并且跳转传值获取值…

Spring Authorization Server Spring Security密码加密

文章目录 一、修改密码编码器二、效果三、注意点1. RegisteredClient2. UserDetailsService 一、修改密码编码器 以BCryptPasswordEncoder举例。 直接将其注册成PasswordEncoder 的Bean即可。 Beanpublic PasswordEncoder passwordEncoder() {// 密码为明文方式 // ret…

“智能检测,精准把控。温湿度检测系统,为您的生活带来全方位的健康保障。”#非标协议项目【下】(分文件编程)

“智能检测,精准把控。温湿度检测系统,为您的生活带来全方位的健康保障。”#非标协议项目【下】(分文件编程) 前言预备知识1温湿度检测系统需求2.分文件编程核心思路3.分文件编程操作4利用分文件操作建立uart.c、lcd1602.c、dht11…

【图形图像的C++ 实现 01/20】 2D 和 3D 贝塞尔曲线

目录 一、说明二、贝塞尔曲线特征三、模拟四、全部代码如下​五、资源和下载 一、说明 以下文章介绍了用 C 计算和绘制的贝塞尔曲线(2D 和 3D)。    贝塞尔曲线具有出色的数学能力来计算路径(从起点到目的地点的曲线)。曲线的形…

YOLOv8改进 | 检测头篇 | 独创RFAHead检测头超分辨率重构检测头(适用Pose、分割、目标检测)

一、本文介绍 本文给大家带来的改进机制是RFAHead,该检测头为我独家全网首发,本文主要利用将空间注意力机制与卷积操作相结合的卷积RFAConv来优化检测头,其核心在于优化卷积核的工作方式,特别是在处理感受野内的空间特征时。RFAConv主要的优点就是增加模型的特征提取能力,…

HiveSQL——sum(if()) 条件累加

注:参考文章: HiveSql面试题10--sum(if)统计问题_hive sum if-CSDN博客文章浏览阅读5.8k次,点赞6次,收藏19次。0 需求分析t_order表结构字段名含义oid订单编号uid用户idotime订单时间(yyyy-MM-dd)oamount订…

ChatGPT高效提问—prompt常见用法(续篇七)

ChatGPT高效提问—prompt常见用法(续篇七) 1.1 零样本、单样本和多样本 ​ ChatGPT拥有令人惊叹的功能和能力,允许用户自由向其提问,无须提供任何具体的示例样本,就可以获得精准的回答。这种特性被称为零样本&#x…

PWM输入输出

PWM(Pulse Width Modulation)即脉冲宽度调制,在具有惯性的系统中,可以通过对一系列脉冲的宽度进行制,来等效地获得所需要的模拟参量,常应用于电机控速、开关电源等领域。 PWM参数 PWM 中有三个重要参数&…

如何开始深度学习,从实践开始

将“如何开始深度学习”这个问题喂给ChatGPT和文心一言,会给出很有专业水准的答案,比如: 要开始深度学习,你可以遵循以下步骤: 学习Python编程语言的基础知识,因为它在深度学习框架中经常被使用。 熟悉线性…

基于tomcat运行jenkins常见的报错处理

目录 1.jenkins.util.SystemProperties$Listener错误 升级jdk11可能遇到的坑 2.java.lang.RuntimeException: Fontconfig head is null, check your fonts or fonts configuration 3.There were errors checking the update sites: UnknownHostException:updates.jenkins.i…

03 动力云客项目之登录功能后端实现

1 准备工作 1.1 创建项目 使用Spring initializr初始化项目 老师讲的是3.2.0, 但小版本之间问题应该不大. 1.2 项目结构 根据阿里巴巴Java开发手册确定项目结构 1.3 分层领域模型 【参考】分层领域模型规约: • DO(Data Object)&am…

(四)elasticsearch 源码之索引流程分析

https://www.cnblogs.com/darcy-yuan/p/17024341.html 1.概览 前面我们讨论了es是如何启动,本文研究下es是如何索引文档的。 下面是启动流程图,我们按照流程图的顺序依次描述。 其中主要类的关系如下: 2. 索引流程 (primary) 我们用postman发送请求&…

【正式】今年第一篇CSDN(纯技术教学)

一、文件上传简介 文件上传漏洞是指用户上传了一个可执行的脚本文件(木马、病毒、恶意脚本、webshell等),并通过此脚本文件获得了执行服务器端命令的能力。上传点一般出现在头像、导入数据、上传压缩包等地方,由于程序对用户上传…

Vue2中v-for 与 v-if 的优先级

在Vue2中,v-for 和 v-if 是常用的指令,它们在前端开发中非常有用。但是,当我们在同一个元素上同时使用这两个指令时,就需要注意它们的优先级关系了。 首先,让我们了解一下v-for和v-if的基本用法。 v-for 是Vue的内置…

Leetcode 213 打家劫舍 II

题意理解: 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果…

three.js 向量方向(归一化.normalize)

效果&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div><div><p><el-button type"primary…