Elasticsearch 调优 (官方文档How To)

How To

Elasticsearch默认是提供了一个很是简单的即开即用体验。用户无需修改什么配置就能够直接使用全文检索、结果高亮、聚合、索引功能。java

可是想在项目中使用高性能的Elasticsearch,有几方面优化方法最好掌握。数据库

本文就是为了引导如何优化。api

常规建议

不要一次返回太大量的搜索结果集

Elasticsearch设计做为一个搜索引擎,很是擅长返回匹配的查询结果。可是,它并不合适像数据库同样,把整个document做为查询结果返回。若是非要这样作,最好仍是使用Scroll这个接口来。缓存

避免索引稀疏

Elasticsearch是基于Lucene进行索引和存储数据的,最佳的工做方式是密集的数据,便是全部的document拥有相同的字段。特别是启用了norms(一般是text字段是默认开启)或者启用了doc_values(一般是numerics, date, ip 或 keyword 是默认开启)的字段。数据结构

缘由是Lucene内部是经过由0到索引 document 总数的 doc_id 来识别 document 。doc_id 用于Lucene api内部之间的通信:例如使用关键词 match 查询获得的doc_id,而后这些doc_id用于检索 norms 的值去计算 score(匹配得分)。这个 norms 查找方式实现目前是经过为每一个 document 保留一个字节。doc_id 能够直接读取该 document 的 norms 值。这种方式好处是能够帮助Lucene快速访问每一个 document ,缺点是每一个 document 还须要额外占多一个字节的存储。多线程

实际上,这就意味着若是一个index里面有M个document,每一个字段的norms就须要M个字节的存储,就算某些字段只是包含在小部份 document 。虽然复杂的类型字段存储使用doc_values,可是同样还会占用存储的。众所周知,fielddata 类型在 pre-2.0以后被替换成 doc_values ,除非 fielddata已经写在硬盘上了,在内存里面的话,也是有这个问题。并发

须要注意的是,稀疏存储会对索引和搜索速度有明显的影响,额外的存储字节虽然不是字段,也是须要花费时间去索引和搜索的。app

固然,index是容许存在少数稀疏状况的,可是若是稀疏数量教大,则会影响整个index的效率。性能

本章节主要集中在 norms 和 doc_values 这两个影响较大的特性。稀疏状况会影响倒排索引(用于索引 text/keyword 字段)和坐标点类型字段(用于索引 geo_point 和 numeric),影响的程度不同。测试

下面有几点推荐能避免稀疏:

避免把无关联的数据放在同一个index

不要把彻底不一样的数据结构 document 放在同一个 index 里面。最好是将这些 document 放到不一样的index里面,能够考虑建立一些较小的index, 用较少的shard去存储。

注意,这个建议不适用于有使用 parent/child 这种带关系的 document 放在同一个 index 的状况。

标准化 document 结构

若是必需把不一样类型的 document 放在同一个 index里面,也是有机会减小稀疏状况的。例如,在 index 内全部的 document 都添加一个时间戳字段,一般叫"timestamp"或者"creation_date",它将会有助于把全部的 document 重命成相同的字段。

避免不一样的 type 放在同一个index

多个 type 放在单个 index 看起来是个简单的方法。可是Elasticsearch并非基于 type来存储的,不一样的 type 在单个 index 也会影响效率。若是 type 没有很是类似的 mapping,建议考虑放到一个单独的 index 上面。

对于不一样的字段禁用 norms 和 doc_values

若是以上建议适用,还须要检查字段是否启用了 norms 和 doc_values。一般只用于过滤而不须要进行打分(匹配度打分)的字段,能够直接禁用 norms 。不用于排序或者聚合的字段能够禁用 doc_values 。注意,若是在已有的 index 作这些变动,是须要对 index 作 reindex的动做。

调优索引速度

使用 bulk 请求

Bulk 批量请求比单次 document 索引请求性能更好。为了验证最优批量请求的大小,能够作一个基准测试,用一个单节点跑一个单 shard 。先尝试索引100个document,而后 200, 而后400,等等。每次运行基准测试就相应加倍 document 的数量。取得索引速度最高的数值,就是最佳的bulk批量请求数。固然,批量请求也不是越多 document 越好。若是并发同时请求,太大的 bulk 请求会使集群内存压力变大,因此建议避免每次请次超过几十M,这样会得到较好的性能。

使用多进程/多线程去发送数据到Elasticsearch

一个单线程发送 bulk 请求彷佛不可以发挥一个集群的索引能力。为了更好地利用集群的资源,应该使用多线程或多进程来发送数据,同时这将有助于减小每次 fsync 的成本。

必定要留意系统是否返回 TOO_MANY_REQUESTS (429) 代码。(一般Java client返回是EsRejectedExecutionException),这是表示Elasticsearch没法跟上当前的索引速度。发生这种状况时能够暂停一下索引一会再试。尝试更换 bulk 一个随机值或理想值。

对于相同大小的 bulk 请求,经过测试能够获得最优的线程数量。能够逐步增长线程数量直至到集群中的机器IO或CPU饱和。

增长 refresh_interval 刷新的间隔时间

index.refresh_interval的默认值是 1s,这迫使Elasticsearch集群每秒建立一个新的 segment (能够理解为Lucene 的索引文件)。增长这个值,例如30s,能够容许更大的segment写入,减后之后的segment合并压力。

在初始化索引时,能够禁用 refresh 和 replicas 数量

若是须要一次加载较大的数据量进 index 里面时,能够先禁用 refresh ,把 index.refresh_interval 设置成为 -1 ,把 index.number_of_replicas 设置成 0。暂时把多个shard副本关闭(即若是当前index发生损坏便用丢失数据),可是这样作能够大大加快索引速度。当初始化索引完成,能够将 index.refresh_interval 和 index.number_of_replicas 设置回原来的值。

禁用 swapping

把操做系统的虚拟内存交换区关闭。sysctl 里面添加 vm.swappiness = 1

确保有空闲的内存给文件系统缓存

文件系统缓存是为了缓冲磁盘的IO操做。至少确保有一半机器的内存保留给操做系统,而不是JAVA VM占用了所有内存。

使用更快的硬件

固然这个不用说了上SSD是最好的了。若是有多个SSD硬盘,能够配置成 RAID 0阵列取得更佳的IO性能。可是任何一个SSD损坏都有可能弄坏 index。一般正确的权衡是优化单的shard存储性能,而后添加 replicas 放在不一样的节点。同时使用 snapshot 快照和 restore 功能去备份 index。

索引 buffer 大小

若是节点在作很是大的索引动做,须要确保 indices.memory.index_buffer_size足够大,最多能够设置为512M的buffer。除此以外增长这个值,性能一般不会获得改善。

Elasticsearch的活跃shard须要使用java的heap内存的百份比或者绝对值去做为一个共享缓冲区。很是活跃的shard天然会使用较频繁。

这个默认值是一般是10%,例如,若是JVM设置为10GB内存为heap,那么就会有1GB的索引缓冲区提供给大量的索引shard。

相关文章
相关标签/搜索