前言

网上关于ES性能优化的文章太多,这里参考官网收集整理下。

官网优化说明:​​how-to​


一、常规建议

1、不要返回数据量非常大的结果集
2、避免出现大文档,即单条索引记录的体积不要过大。
默认情况下, ​​​http.max_content_length​​ 设置为100mb,限制单个索引记录的大小不能超过100mb。

二、优化索引速度

  1. 尽量使用批请求bulk
  2. 采用从多个线程或进程发送数据到ES
  3. 增加索引刷新时间大小​​index.refresh_interval​​,默认1s刷新一次,设置为-1表示关闭索引刷新。
  4. 初始加载数据时禁用副本,将​​index.number_of_replicas​​ 设置为0。
    一般我们在进行大量数据的同步任务和加载的时候,可以先设置index.refresh_interval=-1,index.number_of_replicas=0,关闭自动刷新并将索引的副本数设置为0。待完成数据同步后,再调整回正常值。
  5. 禁用内存交换swapping
  6. 分配足够的内存给文件系统缓存
    文件系统缓存将用于缓冲 I/O 操作。应该确保将运行 Elasticsearch 的计算机的至少一半内存提供给文件系统缓存。
  7. 使用自动生成id
    在索引具有显式 id 的文档时,Elasticsearch 需要检查具有相同 id 的文档是否已存在于同一个分片中,这是一项代价高昂的操作,并且随着索引的增长而变得更加昂贵。
    通过使用自动生成的 id,Elasticsearch 可以跳过此检查,从而加快索引速度。
  8. 使用更快的硬件,比如使用SSD固态硬盘
  9. 索引缓冲区大小​​index_buffer_size​​ 索引缓冲区​​index.memory.index_buffer_size​​默认值是 10%,例如,如果 JVM 10GB 的内存,它将为索引缓冲区提供 1GB。
  10. 使用跨集群复制,避免争抢资源。
  11. 尽量避免使用深度分页,实在不能避免可以采用Scroll 遍历查询或Search After 查询。

三、优化查询速度

  1. 分配足够的内存给文件系统缓存
    Elasticsearch 严重依赖文件系统缓存来加快搜索速度。 通常,您应该​​确保至少有一半的可用内存进入文件系统缓存​​,以便 Elasticsearch 可以将索引的热点区域保留在物理内存中。
  2. 使用更快的硬件
    如果搜索速度受限I/O,可以使用读写速度更快的固态硬盘SSD;
    如果搜索速度受限CPU,那么可以购买速度更快的CPU。
  3. 优化索引文档结构,避免使用连接查询
  4. 搜索尽可能少的字段
    可以通过copy_to将多个字段的值合并到一个字段,这样减少搜索过程匹配的字段。
  5. 预处理索引数据,减少查询过程中的计算消耗
  6. 考虑将索引的mapping中的标识符字段(如id字段)设置为keyword类型
    ​numeric​​ 类型适合范围查询​​range queries​​​​keyword​​ 类型适合等值查询​​term queries​​.
    当然,你也可以使用多字段​​multi-field​​适配多种场景下的查询。
  7. 避免使用脚本
    尽量避免使用脚本排序,脚本计算得分,脚本聚合查询。
  8. 合并只读索引
  9. 热身全局序数,会占用部分JVM 堆空间,可以优化聚合查询性能。
  10. 预热文件系统缓存
    如果重新启动运行 Elasticsearch 的机器,文件系统缓存将是空的,因此操作系统将索引的热点区域加载到内存中需要一些时间,以便快速搜索操作。 您可以使用 ​​index.store.preload​​ 设置根据文件扩展名明确告诉操作系统哪些文件应该立即加载到内存中。
  11. 设置索引存储时的排序方式加快连接查询性能。
  12. 使用首选项帮助优化缓存的使用。
    主要是集群中各个节点上的缓存配置可能存在差异,通过首选项的配置可以统一配置、优化缓存的使用。
  13. 设置正确的副本数来提高吞吐量。
    那么正确的副本数量是多少?如果您的集群有 num_nodes 个节点、num_primaries 主分片,并且您希望最多同时处理 max_failures 个节点故障,那么适合您的副本数为 ​​max(max_failures, ceil(num_nodes / num_primaries) - 1)​​。
  14. 使用更高性能的查询API。比如多用filter少用query。
  15. 使用constant_keyword字段类型提升filter速度。

四、优化磁盘使用

  1. 禁用你不需要的特性
    比如:
    1)不作为查询条件的属性,可以添加在mapping中声明:​​"index": false​​;
    2)text类型字段如果你只匹配而不关注匹配的分数,可以将类型声明为​​match_only_text​​,此字段类型通过删除评分和位置信息来节省大量空间。
  2. 不要使用默认的动态字符串映射
    默认的动态字符串映射会将字符串字段同时作为​​text​​和​​keyword​​进行索引。 如果您只需要其中之一,这是一种浪费。 通常,​​id 字段只需要作为关键字索引,而 body 字段只需要作为文本字段索引​​。
  3. 注意你的分片大小
    说明:更大的分片在存储数据方面会更有效。 要增加分片的大小,可以通过创建具有较少主分片的索引、创建更少的索引(例如通过利用 Rollover API)或使用 Shrink API 修改现有索引来减少索引中主分片的数量。
    但是注意,大的分片也有缺点,例如完整的恢复时间长。
  4. 禁用 _source
    说明:_source 字段存储文档的原始 JSON 正文。 如果您不需要访问它,您可以禁用它。 但是,需要访问 _source 的 API(例如 update 和 reindex)将不起作用。
  5. 使用压缩器best_compression
    说明:_source 和 stored 字段可以很容易地占用不可忽略的磁盘空间量。 可以使用 best_compression 编解码器更积极地压缩它们。
  6. 强制合并Force merge
    说明:Elasticsearch 中的索引存储在一个或多个分片中。 每个分片都是一个 Lucene 索引,由一个或多个段segment组成——磁盘上的实际文件。 更大的段segment对于存储数据更有效。
    强制合并 API 可用于减少每个分片的段数。 在许多情况下,可以通过设置 max_num_segments=1 将段数减少到每个分片一个。
  7. 收缩索引分片数量 Shrink index
    Shrink API 允许您减少索引中的分片数量。 与上面的强制合并 API 一起,这可以显着减少索引的分片和段的数量。
  8. 使用足够的最小数字类型有利于节约磁盘空间
    说明:数字数据选择的字段类型会对磁盘使用产生重大影响。 特别是,整数应使用整数类型(字节、短整型、整数或长整型)存储,浮点数应存储在 scaled_float 中(如果合适)或适合用例的最小类型:使用 float over double,或 half_float over float 将有助于节省存储空间。
  9. 使用索引排序来整理相似的文档,提高压缩率
    说明:Elasticsearch 在存储_source 时,会一次压缩多个文档,以提高整体压缩率。 例如,文档共享相同的字段名是很常见的,而且它们共享一些字段值也很常见,特别是在基数较低或 zipfian 分布的字段上。
    默认情况下,文档按照添加到索引的顺序压缩在一起。 如果您启用了索引排序,那么它们将按排序顺序压缩。 将具有相似结构、字段和值的文档排序在一起应该可以提高压缩率。
  10. 在文档中以相同的顺序放置字段
    说明:由于多个文档被一起压缩成块,如果字段总是以相同的顺序出现,则更有可能在那些 _source 文档中找到更长的重复字符串。
  11. 汇总历史数据
    说明:保留较旧的数据对以后的分析很有用,但由于存储成本,通常会避免。 您可以使用数据汇总以原始数据存储成本的一小部分来汇总和存储历史数据。
  12. 对于时序数据可以采用数据流​​data_stream​​和索引生命周期管理​​ILM​

总结

本文主要是对ES性能调优的一些方案进行了总结。