[转载] Elasticsearch 调优篇 04 - Elasticsearch 索引层面最全优化
1、使用 bulk 批量写入
你如果要往es里面灌入数据的话,那么根据你的业务场景来,如果你的业务场景可以支持让你将一批数据聚合起来,一次性写入 es,那么就尽量采用 bulk 的方式,每次批量写个几千条这样子。
bulk 批量写入的性能比你一条一条写入大量的 document 的性能要好很多。但是如果要知道一个 bulk 请求最佳的大小,需要对单个 es node 的单个 shard 做压测。
先 bulk 写入 100 个 document,然后 200个,400个,以此类推,每次都将 bulk size 加倍一次。如果 bulk 写入性能开始变平缓的时候,那么这个就是最佳的 bulk 大小。
并不是 bulk size 越大越好,而是根据你的集群等环境具体要测试出来的,因为越大的 bulk size 会导致内存压力过大,因此最好一个请求不要发送超过 10MB 的数据量。
先确定一个是 bulk size,此时就尽量是 单线程,一个 es node,一个 shard,进行测试。看看单线程最多一次性写多少条数据,性能是比较好的。
2、使用多线程写入 elasticsearch
单线程发送 bulk 请求是无法最大化 es 集群写入的吞吐量的。
如果要利用集群的所有资源,就需要使用多线程并发将数据 bulk 写入集群中。
为了更好的利用集群的资源,这样多线程并发写入,可以减少每次底层磁盘 fsync 的 次数 和 开销。
首先对单个 es 节点的单个 shard 做压测,比如说,先是 2 个线程,然后是 4 个线程,然后是 8 个线程,16 个,每次线程数量倍增。
一旦发现 es 返回了 TOO_MANY_REQUESTS 的错误,JavaClient 也就是 EsRejectedExecutionException。
此时那么就说明 es 是已经到了一个并发写入的最大瓶颈了,此时我们就知道最多只能支撑这么高的并发写入了。
3、禁用一些无用字段
关闭 _all 配置选项,降低内存使用量以及提升写入速度
内存是宝贵的,每次创建索引的时候要做到充分利用,即
- 有的字段不用的我们坚决不索引
- 各个字段含义清晰就设置为最小类型
- 有些大文本字段如果只用于召回,不用于返回数据,尽可能的只索引不存储
4、refresh 和 replia
这要分两种情况来对待,分别为:全量重建索引 和 实时增量索引
全量重建索引
可以禁止 refresh 和 replica,即 index.refresh_interval = -1 & index.number_of_replicas = 0
此时就不需要创建 segment file,对应文件句柄少了,所消耗的资源也会降低很多
创建的 segment 文件少了,对应 merge 的压力也会降下来
不需要将数据复制到其他的 replica shards 上面去,降低了保证数据一致性的耗时
此时写入的速度会非常快。
一旦写完之后,我们做完对应的 merge optimization 优化就可以将相关参数复原。
实时增量索引
默认的 refresh 间隔是 1s,用 index.refresh_interval 参数可以设置,这样会其强迫 es 每秒中都将内存中的数据写入磁盘中,创建一个新的segment file。
正是这个间隔,让我们每次写入数据后,1s 以后就可以看到。
但是如果我们将这个间隔调大,比如 30s,可以接受写入的数据 30s 后才看到,那么我们就可以获取更大的写入吞吐量,因为 30s 内都是写内存的,每隔 30s 才会创建一个 segment file。
5、使用自动生成的 id
如果我们要手动给 es document 设置一个 id,那么 es 需要每次都去确认一下那个id是否存在于相同的分片中,这个过程是比较耗费时间的。
如果我们使用自动生成的 id,那么es就可以跳过这个步骤,写入性能会更好。对于你的业务中的表id,可以作为 es document 的一个 field。
6、用性能更好的硬件设备
可以使用性能更好的 SSD 磁盘来替代 机械磁盘
作者:星火燎原智勇
原文链接:www.cnblogs.com/liang1101/p/131889...