ES官方调优指南
第一部分:调优索引速度
第二部分:调优搜索速度
第三部分:通用的一些建议
ES发布时带有的默认值,可为es的开箱即用带来很好的体验。全文搜索、高亮、聚合、索引文档 等功能无需用户修改即可使用,当你更清楚的知道你想如何使用es后,你可以作很多的优化以提高你的用例的性能,下面的内容告诉你 你应该/不应该 修改哪些配置。
第一部分:调优索引速度
使用批量请求批量请求将产生比单文档索引请求好得多的性能。
为了知道批量请求的最佳大小,您应该在具有单个分片的单个节点上运行基准测试。首先尝试索引100个文件,然后是200,然后是400,等等。当索引速度开始稳定时,您知道您达到了数据批量请求的最佳大小。在配合的情况下,最好在太少而不是太多文件的方向上犯错。请注意,如果群集请求太大,可能会使群集受到内存压力,因此建议避免超出每个请求几十兆字节,即使较大的请求看起来效果更好。
发送端使用多worker/多线程向es发送数据 发送批量请求的单个线程不太可能将Elasticsearch群集的索引容量最大化。为了使用集群的所有资源,您应该从多个线程或进程发送数据。除了更好地利用集群的资源,这应该有助于降低每个fsync的成本。
请确保注意TOOMANYREQUESTS(429)响应代码(Java客户端的EsRejectedExecutionException),这是Elasticsearch告诉您无法跟上当前索引速率的方式。发生这种情况时,应该再次尝试暂停索引,理想情况下使用随机指数回退。在此我向大家推荐一个架构学习交流圈。交流学习伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
与批量调整大小请求类似,只有测试才能确定最佳的worker数量。这可以通过逐渐增加工作者数量来测试,直到集群上的I / O或CPU饱和。
1.调大 refresh interval
默认的index.refresh_interval是1s,这迫使Elasticsearch每秒创建一个新的分段。增加这个价值(比如说30s)将允许更大的部分flush并减少未来的合并压力。
2.加载大量数据时禁用refresh和replicas
如果您需要一次加载大量数据,则应该将index.refreshinterval设置为-1并将index.numberofreplicas设置为0来禁用刷新。这会暂时使您的索引处于危险之中,因为任何分片的丢失都将导致数据 丢失,但是同时索引将会更快,因为文档只被索引一次。初始加载完成后,您可以将index.refreshinterval和index.numberofreplicas设置回其原始值。
3.设置参数,禁止OS将es进程swap出去
您应该确保操作系统不会swapping out the java进程,通过禁止swap
4.为filesystem cache分配一半的物理内存
文件系统缓存将用于缓冲I / O操作。您应该确保将运行Elasticsearch的计算机的内存至少减少到文件系统缓存的一半。
5.使用自动生成的id(auto-generated ids)
索引具有显式id的文档时,Elasticsearch需要检查具有相同id的文档是否已经存在于相同的分片中,这是昂贵的操作,并且随着索引增长而变得更加昂贵。通过使用自动生成的ID,Elasticsearch可以跳过这个检查,这使索引更快。
6.买更好的硬件
搜索一般是I/O 密集的,此时,你需要
为filesystem cache分配更多的内存
使用SSD硬盘
使用local storage(不要使用NFS、SMB 等remote filesystem)
亚马逊的 弹性块存储(Elastic Block Storage)也是极好的,当然,和local storage比起来,它还是要慢点
如果你的搜索是 CPU-密集的,买好的CPU吧
7.加大 indexing buffer size
默认值是10%,通常很多:例如,如果你给JVM 10GB的内存,它会给索引缓冲区1GB,这足以承载两个索引很重的分片。
8.禁用fieldnames字段
fieldnames字段引入了一些索引时间开销,所以如果您不需要运行存在查询,您可能需要禁用它。在此我向大家推荐一个架构学习交流圈。交流学习伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多
9.剩下的,再去看看 “调优 磁盘使用”吧
中有许多磁盘使用策略也提高了索引速度。
第二部分-调优搜索速度
1.filesystem cache越大越好
为了使得搜索速度更快, es严重依赖filesystem cache
一般来说,需要至少一半的 可用内存 作为filesystem cache,这样es可以在物理内存中 保有 索引的热点区域(hot regions of the index)
2.用更好的硬件
搜索一般是I/O bound的,此时,你需要
为filesystem cache分配更多的内存
使用SSD硬盘
使用local storage(不要使用NFS、SMB 等remote filesystem)
亚马逊的 弹性块存储(Elastic Block Storage)也是极好的,当然,和local storage比起来,它还是要慢点
如果你的搜索是 CPU-bound,买好的CPU吧
3.文档模型(document modeling)
文档需要使用合适的类型,从而使得 search-time operations 消耗更少的资源。咋作呢?答:避免 join操作。具体是指
nested 会使得查询慢 好几倍
parent-child关系 更是使得查询慢几百倍
如果 无需join 能解决问题,则查询速度会快很多
4.预索引 数据
根据“搜索数据最常用的方式”来最优化索引数据的方式
举个例子:所有文档都有price字段,大部分query 在 fixed ranges 上运行 range aggregation。你可以把给定范围的数据 预先索引下。然后,使用 terms aggregation
5.Mappings(能用 keyword 最好了)
数字类型的数据,并不意味着一定非得使用numeric类型的字段。
一般来说,存储标识符的 字段(书号ISBN、或来自数据库的 标识一条记录的 数字),使用keyword更好(integer,long 不好哦,亲)
6.避免运行脚本
一般来说,脚本应该避免。如果他们是绝对需要的,你应该使用painless和expressions引擎。
7.搜索rounded 日期
日期字段上使用now,一般来说不会被缓存。但,rounded date则可以利用上query cache
rounded到分钟等
8.强制merge只读的index
只读的index可以从“merge成 一个单独的 大segment”中收益
9.预热 全局序数(global ordinals)
全局序数 用于 在 keyword字段上 运行 terms aggregations
es不知道 哪些fields 将 用于/不用于 term aggregation,因此 全局序数 在需要时才加载进内存
但,可以在mapping type上,定义 eagerglobalordinals==true,这样,refresh时就会加载 全局序数
10.预热 filesystem cache
机器重启时,filesystem cache就被清空。OS将index的热点区域(hot regions of the index)加载进filesystem cache是需要花费一段时间的。
设置 index.store.preload 可以告知OS 这些文件需要提早加载进入内存
11.使用索引排序来加速连接