提高索引的写入速度是一个优化的系统性能的重要角度,有哪些手段可以提高索引的写入速度呢?

批量操作:使用 bulk requests

Bulk requests 将产生比单文档索引请求更好的性能。

批量操作的请求数也不能盲目的增大,否则网络传输也将会耗费很多的时间。可以通过在单个节点上运行基准测试,选择一个较合适的批量的大小。首先尝试一次索引 100 个文档,然后是 200 个,然后是 400 个等。在每次基准测试运行中,批量请求中的文档数量翻倍。当索引速度开始趋于平稳时,就说明达到了数据批量请求的最佳大小。

并行操作:使用多线程发送请求

仅仅使用 bulk resquests 的单个线程不太可能达到 Elasticsearch 集群的最大吞吐量。为了使用集群的所有资源,应该尝试使用多个线程发送数据。除了更好地利用集群的资源外,这应该有助于降低每个 fsync 的成本。

与调整 bulk requests 的大小类似,只有经过测试才能确定最佳的线程数量是多少。这可以通过逐渐增加线程的数量来测试,直到集群上的 I/O 或 CPU 饱和。

刷新间隔:取消或增加刷新间隔

Refresh 操作可以是更改的文档立即被搜索到,但是这个操作是耗费资源的,如果经常执行此操作,会影响索引的写入速度。

默认情况下,Elasticsearch 每秒定期执行 refresh 操作来刷新索引(仅在最近 30 秒内收到一个或多个搜索请求的索引上)。

如果搜索流量很少(例如每 5 分钟不到一个搜索请求)并且想要优化索引速度,这是最佳配置。这个配置项可以在不执行搜索的默认情况下自动的批量优化索引。

另一方面,如果搜索流量较大,则意味着 Elasticsearch 将每 1 秒刷新一次您的索引。如果业务允许,那么增大 index.refresh_interval 到更大的值(例如 30s)可能有助于提高索引速度。

之前有一次事故,就是因为 refresh_interval 被程序异常修改为了 -1,导致业务搜索时,无法及时的检索到最新的数据。所以此字段如何设置,应当顾及业务对数据实时性的容忍度。

初始数据时:禁用副本

如果有大量的数据需要写入到索引中,通过将副本数修改为0可以加快索引速度。

但没有副本意味着丢失单个节点可能会导致数据丢失,因此在上述的数据写入过程完成后,需要将 index.number_of_replicas 设置回其原始值。

尤其是新建的索引时,如果有数据需要刷到索引里,将副本数设为0是很有帮助的。

使用自动生成的 ID编辑

在索引具有显式 id 的文档时,Elasticsearch 需要检查同一分片中是否已经存在具有相同 id 的文档,这是一项昂贵的操作,并且随着索引的增长而变得更加昂贵。通过使用自动生成的 id,Elasticsearch 可以跳过此检查,从而加快索引速度。

总结

以上的几个可以着手优化的点,是开发者需要重点关注的,除了这些之外,还有一些是运维需要关注的,这些在官方文档中也有提及。

参考文档

官方文档:tune-for-indexing-speed