文章目录

  • 一、简介
    • 1.1、元数据字段
    • 1.2、索引映射参数
  • 二、优化措施
    • 2.1、禁用对你来说不需要的特性
    • 2.2、禁用doc_values
    • 2.3、不要使用默认的动态字符串映射
    • 2.4、观察分片大小
    • 2.5、禁用source
    • 2.7、使用best_compression
    • 2.8、Fource Merge
    • 2.9、Shrink Index
    • 2.10、数值类型长度够用就好
    • 2.11、使用索引排序来排列类似的文档
    • 2.12、在文档中以相同的顺序放置字段
  • 三、测试数据
  • 关注我的公众号【宝哥大数据】, 更多干货

一、简介

优化磁盘使用量与建立索引时的映射参数索引元数据字段密切相关,在介绍具体的优化措施之前,我们先介绍这两方面的基础知识。

1.1、元数据字段

每个文档都有与其相关的元数据,比如_index、_type (ES7.x后废弃)_id。 当创建映射类型时,可以定制其中一些元数据字段。 下面列出了与本文相关的元数据字段,完整的介绍请参考官方手册:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-fields.html

  • _source:原始的 JSON 文档数据
  • _all :索引所有其他字段值的一种通用字段,这个字段中包含了所有其他字段的值。允许在搜索的时候不指定特定的字段名,意味着“从全部字段中搜索”,例如:http://localhost:9200/website/_search?q=keyword

_all 字段是一个全文字段,有自己的分析器。从 ES 6.0 开始该字段被禁用。之前的版本默认启用,但字段的 store 属性为false,因此它不能被查询后取回显示。

1.2、索引映射参数

索引创建时可以设置很多映射参数,各种映射参数的详细说明可参考官方手册:https://www.elastic.co/guide/en/elasticsearch/reference/master/mapping-params.html,这里只介绍与本文相关的参数。

  • index:控制字段值是否被索引。它可以设置为true或false,默认为true。未被索引的字段不会被查询到,但是可以聚合。除非禁用doc_values。
  • doc_values:默认情况下,大多数字段都被索引,这使得它们可以搜索。倒排索引根据term找到文档列表,然后获取文档原始内容。但是排序和聚合,以及从脚本中访问某个字段值,需要不同的数据访问模式,它们不仅需要根据term找到文档,还要获取文档中字段的值。这些值需要单独存储。doc_values 就是用来存储这些字段值的。它是一种存储在磁盘上的列式存储,在文档索引时构建,这使得上述数据访问模式成为可能。它们以面向列的方式存储与 _source 相同的值,这使得排序和聚合效率更高。几乎所有字段类型都支持doc_values,但被分析(analyzed)的字符串字段除外(即text类型字符串)。doc_values 默认启用。
  • store:默认情况下,字段值会被索引使它们能搜索,但它们不会被存储( stored)。意味着可以通过这个字段查询,但不能取回它的原始值。

但这没有关系。因为字段值已经是 _source 字段的一部分, 它是被默认存储的。如果只想取回一个字段或少部分字段的值,而不是整个 _source,则可以通过source filtering达到目的。

在某些情况下,存储字段是有意义的。例如,如果有一个包含标题、日期和非常多的内容字段的文档,则可能希望只检索标题和日期,而不需要从大型source 字段中提取这些字段:

例如

# 我们创建一个索引:
PUT chb_test1
{"mappings": {"properties": {"title": {"type" :"text" ,"store": true },"content":{"type": "text" }}}
}然后写入一条数据:
PUT chb_test1/_doc/1
{"title":"Some short title","content": "A very long content field.. ."
}下面的搜索将返回title 字段的值:
GET my_index/_search
{"stored fields": { "title" }
}

还有一种情况可能用到存储字段,就是不在_source 中出现的字段(例如,copy_to字段)。

doc_values 和存储字段(“stored”:ture) 都属于正排内容,两者的设计初衷不同。

stored fields 被设计为优化存储,doc_values 被设计为快速访问字段值。搜索可能会访问很多doc values 中的字段,所以必须能够快速访问,我们将doc_values 用于聚合、排序,以及脚本中。现在,ES中的许多特性都会自动使用doc_values

另一方面,存储字段仅用于返回前几个最匹配文档的字段值,默认情况下ES只将其用于这种情况,解压存储字段,将其发送给客户端。为少量文档获取存储字段还好。它不能在查询的时候使用,否则会让查询变得非常慢。脚本中可以访问存储字段,但最好不要那么做。

二、优化措施

2.1、禁用对你来说不需要的特性

默认情况下,ES为大多数的字段建立索引,并添加到doc_values, 以便使之可以被搜索和聚合。但是有时候不需要通过某些字段过滤,例如,有一个名为foo的数值类型字段,需要运行直方图,但不需要在这个字段上过滤,那么可以不索引这个字段:

PUT chb_test2
{"mappings": {"properties": {"foo": {"type": "integer","index": false}}}
}

text类型的字段会在索引中存储归一因子(normalization factors), 以便对文档进行评分,如果只需要在文本字段上进行匹配,而不关心生成的得分,则可以配置ES不将norms写入索引:

PUT chb_test2
{"mappings": {"properties": {"foo": {"type": "text","norms": false}}}
}

text类型的字段默认情况下也在索引中存储频率和位置。频率用于计算得分,位置用于执行短语(phrase) 查询。如果不需要运行短语查询,则可以告诉ES不索引位置:

PUT chb_test2
{"mappings": {"properties": {"foo": {"type": "text","index_options": "freqs"}}}
}

text类型的字段上,index_options 的默认值为positionsindex_options 参数用于控制添加到倒排索引中的信息。

freqs文档编号和词频被索引,词频用于为搜索评分,重复出现的词条比只出现一次的词条评分更高。positions 文档编号、词频和位置被索引。位置被用于邻近查询(proximity queries)和短语查询( phrase queries )。

完整的index_options 选项请参考官方手册:https://www.elastic.co/guide/en/elasticsearch/reference/master/index-options.html。此外,如果也不关心评分,则可以将ES配置为只为每个term索引匹配的文档。仍然可以在这个字段上搜索,但是短语查询会出现错误,评分将假定在每个文档中只出现一次词汇。

PUT chb_test2
{"mappings": {"properties": {"foo": {"type": "text","norms": false, "index_options": "freqs"}}}
}

2.2、禁用doc_values

所有支持doc_values的字段都默认启用了doc_values。如果确定不需要对字段进行排序或聚合,或者从脚本访问字段值,则可以禁用doc value以节省磁盘空间:

PUT chb_test3
{"mappings": {"properties": {"status_code": {"type": "keyword","doc_values": false}}}
}

2.3、不要使用默认的动态字符串映射

默认的动态字符串映射会把字符串类型的字段同时索引为textkeyword。如果只需要其中之一,则显然是一种浪费。通常,id字段只需作为keyword类型进行索引,而body字段只需作为text类型进行索引。

要禁用默认的动态字符串映射,则可以显式地指定字段类型,或者在动态模板中指定将字符串映射为text或keyword。下例将字符串字段映射为keyword:

PUT chb_test4
{"mappings": {"dynamic_templates": [{"strings": {"match_mapping_type": "string","mapping": {"type": "keyword"}}}]}
}

2.4、观察分片大小

较大的分片可以更有效地存储数据。为了增加分片大小,可以在创建索引的时候设置较少的主分片数量,或者使用 shrinkAPI 来修改现有索引的主分片数量。但是较大的分片也有缺点,例如,较长的索引恢复时间。

2.5、禁用source

_source字段存储文档的原始内容。如果不需要访问它,则可以将其禁用。但是,需要访问_source 的API将无法使用,至少包括下列情况:

  • update、update_ by_ query、 reindex
  • 高亮搜索
  • 重建索引(包括更新mapping、分词器,或者集群跨大版本升级可能会用到)
  • 调试聚合查询功能,需要对比原始数据

2.7、使用best_compression

_source 和设置为"store": true的字段占用磁盘空间都比较多。默认情况下,它们都是被压缩存储的。默认的压缩算法为LZ4,可以通过使用best_compression来执行压缩比更高的算法: DEFLATE。 但这会占用更多的CPU资源。

PUT chb_test4
{"settings": {"index": {"codec": "best_compression"}}
}

2.8、Fource Merge

一个ES索引由若干分片组成,一个分片有若干Lucene分段,较大的Lucene分段可以更有效地存储数据。

使用_forcemerge API来对分段执行合并操作,通常,我们将分段合并为一个单个的分段:max_num_segments=1。

2.9、Shrink Index

Shrink API允许减少索引的分片数量,结合上面的Force Merge API,可以显著减少索引的分片和Lucene分段数量。

2.10、数值类型长度够用就好

为数值类型选择的字段类型也可能会对磁盘使用空间产生较大影响,整型可以选择byte、short、integer、long, 浮点型可以选择scaled_float、float、double、half_float,每个数据类型的字节长度是不同的,为业务选择够用的最小数据类型,可以节省磁盘空间。

2.11、使用索引排序来排列类似的文档

当ES存储_source时,它同时压缩多个文档以提高整体压缩比。例如,文档共享相同的字段名,或者它们共享一些字段值,特别是在具有低基数或zipfian 分布(参考https://en.wikipedia.org/wiki/Zipf%27s_law) 的字段上。

默认情况下,文档按照添加到索引中的顺序压缩在一起。如果启用了索引排序,那么它们将按排序顺序压缩。对具有相似结构、字段和值的文档进行排序可以提高压缩比。

关于索引排序的详细内容请参考官方手册: https://www.elastic.co/guide/en/elasticsearch/reference/master/index-modules-index-sorting.html。

2.12、在文档中以相同的顺序放置字段

由于多个文档被压缩成块,如果字段总是以相同的顺序出现,那么在这些source 文档中可以找到更长的重复字符串的可能性更大。

三、测试数据

下面是在笔者的环境中,使用测试数据调整不同索引方式的测试结论。测试数据为单个文档十几个字段,大小为800字节左右。数据样本如下:

在其他条件不变的情况下,调整单个参数,测试结果如下:

  • 禁用_source, 空间占用量下降30%左右
  • 禁用doc_values,空间占用量下降10%左右
  • 压缩算法将LZ4改为Deflate,空间占用量可以下降15%~25%

对于相似结构的数据,本文的测试结果可作一定参考,实际业务最好使用自己的样本数据进行压力测试以获取准确的结果。

关注我的公众号【宝哥大数据】, 更多干货

《Elasticsearch 源码解析与优化实战》第20章:磁盘使用量优化相关推荐

  1. ElasticSearch源码解析(五):排序(评分公式)

    ElasticSearch源码解析(五):排序(评分公式) 转载自:http://blog.csdn.net/molong1208/article/details/50623948   一.目的 一个 ...

  2. 渣渣菜鸡的 ElasticSearch 源码解析 —— 启动流程(上)

    关注我 转载请务必注明原创地址为:http://www.54tianzhisheng.cn/2018/08/11/es-code02/ 前提 上篇文章写了 ElasticSearch 源码解析 -- ...

  3. Elasticsearch源码解析:环境搭建

    在之前学习Redis的过程中,我就是一边通过文档/视频学习,一边阅读源码.我发现两种方法可以相辅相成,互相补充.阅读文档可以帮助我们快速了解某个功能,阅读源码有助于我们更深入的理解这一功能的实现及思想 ...

  4. SpringSecurity 源码解析 | 加JWT 实战 之 授权流程源码分析

    前两篇分析了SpringSecurity 认证源码和自定义认证流程,本片主要讲下另一个核心授权. 简单理解: 登录认证是用来确认用户是否能访问系统. 授权就是:你认证通过之后,还要检查是你是否满足资源 ...

  5. 《Elasticsearch 源码解析与优化实战》样章-第 6 章 数据模型

    1.概述 转载:https://www.easyice.cn/archives/300 这里面有一些是我以前不知道的,先记录一下,以后看的时候加深理解.

  6. redistemplate使用_spring-boot-starter-data-redis源码解析与使用实战

    我们以spring-boot-starter-data-redis-2.1.7为例,starter本身没有包含任何代码,只是引入了spring-data-redis的依赖,因此肯定是在spring-b ...

  7. clickhouse原理解析与开发实战 pdf_重识SSM,“超高频面试点+源码解析+实战PDF”,一次性干掉全拿走...

    重识SSM,"超高频面试点"+"源码解析"+"实战PDF",一次性干掉全拿走!! 01 超高频面试点知识篇 1.1 Spring超高频面试点 ...

  8. tns03505 无法解析名称_SpringBootWeb源码解析SpringMVC自动配置

    SpringMVC自动配置 在 Spring Boot 中引入了 spring-boot-starter-web 依赖,并完成了 DispatcherServlet 的自动配置之后,便会通过 WebM ...

  9. BAT高级架构师合力熬夜15天,肝出了这份PDF版《Android百大框架源码解析》,还不快快码住。。。

    前言 为什么要阅读源码? 现在中高级Android岗位面试中,对于各种框架的源码都会刨根问底,从而来判断应试者的业务能力边际所在.但是很多开发者习惯直接搬运,对各种框架的源码都没有过深入研究,在面试时 ...

最新文章

  1. redis学习笔记-持久化
  2. 019_MySQL正则表达式
  3. java 发送cookie_Java如何在Servlet中发送cookie?
  4. C#应用视频教程3.1 USB工业相机测试
  5. 【最短路】【Floyed】医院设置(ssl 1614)
  6. informatica中元数据管理
  7. Microsoft visual studio关闭安全检查
  8. Css中实现一个盒子固定宽度,另一个盒子宽度自适应的方法
  9. add php support,WordPress add_theme_support() 函数详解
  10. ArcGIS 10研究(二) 之Mobile新特性
  11. Android打开系统文件管理器
  12. Base64基本原理及简单应用
  13. java过载保护_微服务过载保护原理与实战「纯干货」
  14. 基于数字孪生的IBV智能建筑可视化系统了解一下
  15. 相对于父容器(取值:true / false)帧布局(FrameLayout)
  16. 知识产权-软考知识点-3
  17. 物联网卡是什么?物联网卡有哪些功能?
  18. 手游测试人才稀缺,兼容性问题突出
  19. 详解ENet | CPU可以实时的道路分割网络
  20. 线性表 :: 顺序存储结构的实现

热门文章

  1. GDBus之信号使用
  2. SAP中质量检验计划中采样确定过程图示
  3. Metronic 对话 chat
  4. 浏览器打开是全屏的,在整个桌面显示,看不到下方的任务栏
  5. ubuntu 20.04安装wps,并安装缺失字体
  6. java雷达数据解析_radar: 基于python pycinrad 以及多种类库 编写基于java 的雷达基数据统一格式读取...
  7. 最大的矩形问题(201312-3)
  8. java第二作业 手动输入数赋值给数组 求最大值最小值 ,,,,,,输入一个数字 插如数组里 并且保持降序
  9. WUSTOJ 1279: Wallace and His Pet(Java)
  10. 利用python实现星轨合成