当前位置: 首页 > news >正文

ES_数据存储知识

一、 _source 字段:数据的“真相之源”

1. 是什么?
_source 是一个独立的、特殊的元字段。它存储了你在索引文档时提交的原始JSONbody的完整内容

2. 工作原理与用途

  • 写入:当你索引一个文档 {"title": "My Book", "price": 29.99},这个完整的JSON对象就会被原封不动地存储到 _source 字段中。
  • 读取
    • 搜索返回:当你执行搜索请求,默认返回的 hits.hits._source 里的数据,就是直接从 _source 字段提取的,并非从倒排索引中重建。这是为什么ES搜索返回结果如此之快的原因之一。
    • 重建索引/更新update API和reindex API都严重依赖 _source 字段。更新操作本质上是“获取文档 -> 修改 _source -> 重新索引”;重建索引则是直接从源索引读取 _source 来写入新索引。
    • 高亮(Highlighting):高亮功能通常需要访问原始文本内容来确定字符位置,_source 是其数据来源之一。

3. 禁用 _source
你可以通过映射禁用 _source,但强烈不建议这样做

PUT my_index
{"mappings": {"_source": {"enabled": false},"properties": {...}}
}

禁用后果

  • 无法使用 update API。
  • 无法直接通过 _reindex API 迁移数据。
  • 无法使用高亮(除非显式地将高亮所需字段设置为 "store": true)。
  • 无法在查询结果中看到原始文档。
  • 调试困难。

最佳实践永远不要禁用 _source。如果担心磁盘占用,可以通过索引压缩、使用更高效的硬件等方式解决,而不是牺牲核心功能。


二、 doc_values:列式存储的基石

1. 是什么?
doc_values 是默认开启的、在磁盘上的、基于列式存储的数据结构。它的存在是为了高效地完成排序(Sorting)、聚合(Aggregation)和脚本访问(Scripting)

2. 为什么需要它?
倒排索引是为“查找包含某个词项的文档”而优化的(即搜索)。但要回答“对某个字段进行聚合或排序”就非常困难且低效,因为这需要遍历所有文档并获取字段值。

doc_values 解决了这个问题。它为所有支持它的字段类型(如 keyword, numeric, date, geo_point, ip 等,但不包括 text)在索引时额外创建了一个列式存储结构。

Documentprice (Field Value)
Doc_1100
Doc_2200
Doc_3150

3. 工作原理与用途

  • 列式存储:数据按列(字段)存储,而不是按行(文档)。这使得ES可以高效地:
    • 排序:快速遍历一列中的所有值。
    • 聚合:计算一列中值的总和、平均值、百分位数等。
    • 脚本访问:在脚本中引用 doc['price'].value 时,数据来源于 doc_values
  • 磁盘存储doc_values 存储在磁盘上,但OS会将其缓存到文件系统缓存中,以提供高速访问。

4. 禁用 doc_values
你可以按字段禁用 doc_values,但仅在你100%确定该字段永远不会用于排序、聚合或脚本时才可以这样做。这可以节省磁盘空间。

"my_field": {"type": "keyword","doc_values": false // 谨慎禁用!
}

三、 fielddata:内存中的倒排索引

1. 是什么?
fielddatadoc_values内存版互补方案,主要用于 text 字段。

2. 为什么需要它?
text 字段默认会被分词(analyzed),因此它们默认没有 doc_values。如果你突然需要对一个 text 字段进行聚合或排序(例如,对 product_name 这个 text 字段做 terms 聚合),ES需要能够通过文档ID快速找到该文档的字段值。

fielddata 就是将所有分词后的词项包含它们的文档的对应关系,从磁盘上的倒排索引加载到JVM堆内存中形成的数据结构。这是一个昂贵且延迟高的操作。

3. 工作原理与用途

  • 默认关闭,需要手动在映射中为 text 字段开启。
  • 数据存储在 JVM堆内存中,极易导致内存溢出(OOM)和集群不稳定。
  • 主要用于 text 字段的聚合和排序。
PUT my_index/_mapping
{"properties": {"my_text_field": {"type": "text","fielddata": true // 警告:请谨慎开启!}}
}

4. fielddata vs doc_values

特性doc_valuesfielddata
存储介质磁盘(利用文件系统缓存)JVM堆内存
创建时机索引时首次聚合/排序时(延迟加载)
默认状态对支持字段默认开启text 字段默认关闭
性能影响低,磁盘操作高,极易引起GC压力和OOM
适用字段keyword, numeric, date, iptext

最佳实践极力避免开启 fielddata。如果需要对字符串进行聚合和排序,优先使用 keyword 类型或多字段:

"product_name": {"type": "text",       // 用于全文搜索"fields": {"raw": {            // 用于聚合和排序"type": "keyword" // 使用keyword类型,它天然有doc_values支持}}
}

查询时使用 product_name.raw 进行聚合。


四、 store 参数:存储“额外”的副本

1. 是什么?
默认情况下,字段值存储在 _source 中。如果你设置 "store": true,ES会额外将该字段的值单独存储在一份空间中。

2. 为什么需要它?
主要目的是在查询结果中返回某些特定的、未被 _source 包含的字段,或者_source 中提取某个字段开销很大时(因为 _source 需要被压缩和解压)。

常见误区"store": true 并不会让字段变得可搜索!字段是否可搜索只由 "index" 参数控制。它只影响该字段的值是否可以被单独返回。

3. 使用场景
场景一:_source 被禁用,但你仍希望返回某个字段的值。
场景二:_source 非常大(例如包含一个很长的文本内容),但你只需要频繁返回其中的一两个小字段(如 title, date)。单独存储这些小字段可以避免在每次查询时解压整个庞大的 _source,提升性能。

PUT my_index
{"mappings": {"_source": {"enabled": true // _source 仍然启用},"properties": {"title": {"type": "text","store": true // 额外存储一份},"content": {"type": "text","store": false // 不额外存储,只在 _source 里}}}
}// 查询时,使用 `stored_fields` 来指定返回哪些存储的字段
GET my_index/_search
{"stored_fields": [ "title" ], // 只返回显式声明为store=true的字段"query": {...}
}

最佳实践:这是一个非常高级的优化选项。在绝大多数情况下,你不需要设置 "store": true。依赖 _source 是更简单、更通用的做法。


五、 null_value:处理空值的利器

1. 是什么?
null_value 参数允许你用一个指定的值(如 "NULL", 0, -1)来替换显式的 null,以便该字段可以被搜索和聚合。

2. 为什么需要它?
在ES中,一个字段的值为 null、空数组 [] 或者根本不存在,在Lucene底层是等价的——它们都没有被索引。这意味着你无法通过 term 查询找到值为 null 的文档。

3. 使用方法

"status_code": {"type": "keyword","null_value": "NULL" // 将显式的null替换为字符串"NULL"
}

索引数据

{ "status_code": "active" }
{ "status_code": null }     // 实际在索引中,这个字段的值是 "NULL"
{ }                         // 这个文档的status_code字段不存在,值仍是null

查询
现在,你可以找到所有 status_codenull 的文档了:

GET my_index/_search
{"query": {"term": {"status_code": "NULL" // 搜索被替换后的值}}
}

最佳实践:对于需要区分“空值”业务的字段(如状态码、标签、分类),使用 null_value 可以保证数据的可查询性。


总结与核心建议

概念核心用途默认值建议
_source存储原始文档,用于结果返回、更新、重建索引true永远不要禁用
doc_values为排序、聚合、脚本提供磁盘上的列式存储true (对支持字段)不要禁用,除非绝对确定用不到
fielddatatext 字段的排序聚合提供内存中的数据false极力避免开启,用keyword多字段替代
store额外存储字段值,用于特定优化场景false大多数情况不需要,优先使用_source
null_valuenull替换为可索引/聚合的默认值null按需使用,用于需要查询空值的业务字段

作为一名架构师,你的目标是:

  1. 保证功能:确保 _source 可用。
  2. 追求性能:善用 doc_values,避免使用 fielddata
  3. 精细优化:在明确收益后,再考虑使用 storenull_value 这类高级参数。

透彻理解这些底层机制,将使你能够设计出既高效又稳健的Elasticsearch系统,从容应对各种复杂的业务场景。

http://www.dtcms.com/a/343338.html

相关文章:

  • 基于SpringBoot的宠物用品系统【2026最新】
  • odoo-063 pip 安装 Segmentation fault (core dumped),曲线救国
  • Vue3 + TypeScript全局阻止非输入区域的Backspace键,防止回退页面
  • Redis实战-基于Session实现分布式登录
  • 深度学习——yolo学习
  • AI模型部署 - 大语言模型(LLM)部署技术与框架
  • Android auncher3实现简单的负一屏功能
  • 基于YOLOv8-SEAttention与LLMs融合的农作物害虫智能诊断与防控决策系统
  • 运动数据采集如何帮助克里斯·凯尔飞跃迎面驶来的F1赛车
  • 基于IEEE-754浮点数格式的matlab仿真
  • Day24 目录遍历、双向链表、栈
  • Mac电脑 3D建模工具--犀牛Rhino
  • 【个人网络整理】NOIP / 省选 /NOI 知识点汇总
  • 视频孪生技术在城市政务数字化转型中的应用与价值探索
  • ES_映射
  • Nacos-10--认识Nacos中的Raft协议(Nacos强一致性的实现原理)
  • VirtualBox 安装 Ubuntu Server 系统及 Ubuntu 初始配置
  • 区块链联邦学习思路一
  • 14、软件实现与测试
  • 实践题:智能健康监测系统设计方案
  • centos下安装Nginx(搭建高可用集群)
  • 亚马逊产品排名提升策略:从传统运营到AI驱动的智能化突破
  • 《信任链:幽灵签名》
  • 近端策略优化 (PPO) 算法深度解析
  • 智能求职推荐系统
  • mfc140u.dll文件是什么?解决mfc140u.dll文件丢失的有效解决方法分享
  • 密码管理中明文密码与空密码的危害与预防
  • 民国悬爱网剧《春迟》腾讯独播,石雨晴担纲联合出品人与联合制片人
  • Redis 主从复制(重点理解流程和原理)
  • Windows下服务封装