# 索引速率调优

原文链接 : [https://www.elastic.co/guide/en/elasticsearch/reference/5.3/tune-for-indexing-speed.html](https://www.elastic.co/guide/en/elasticsearch/reference/5.3/tune-for-indexing-speed.html)

译文链接 : [索引速率调优](/pages/viewpage.action?pageId=10027117)

贡献者 : @李坚，[ApacheCN](/display/~apachecn)，[Apache中文网](/display/~apachechina)

## 使用批量请求

_Bulk requests（批量请求）_会比单文档索引请求性能更优。确认_bulk requests（ 批量请求）_的最佳大小，要在单个节点上使用单个分片进行基准测试来获取。首先尝试一次性索引 100 个 _documents（文档）_，然后200个，然后400个；在每个基准测试中，下一次索引的 documents（文档）数是上一次的两倍。当索引速率达到最高时，就可以确认每次 _bulk requests（ 批量请求）_的最佳 _documents（文档）_数大小了。在领带情况下，最好是发生的错误越少越好而不是索引的_documents（文档）_越多越好。当心，很多客户端同时发送数据产生非常大的 _bulk requests（ 批量请求）_使集群处在内存压力下；即使看起来较大的请求会更好，还是建议每个请求不要超出几十兆字节。

## 使用多线程向Elasticsearch发送数据

单线程的 _bulk requests（ 批量请求）_达不到 _Elasticsearch_ 集群的最大索引性能。为了充分利用集群的资源，应该使用多个线程或进程发送数据。除了更好地利用集群的资源外，这也有助于降低每个 fsync 的成本。当你看到**_TOO_MANY_REQUESTS（429）_**响应代码（_EsRejectedExecutionException with the Java client_），这是 _Elasticsearch_ 告诉您无法跟上当前索引速率了。当这种情况发生的时候，先暂停索引一会，然后再次尝试，

ideally with randomized exponential backoff（理论上会有随机指数回退）。类似于调整_ bulk requests（ 批量请求）_的大小，只有通过测试才可以知道最适合的线程数。 这个可以通过逐渐增加线程的数量进行测试，直到集群上的 _I / O 或 CPU_ 饱和为止。

## 增大刷新间隔

默认  _[`index.refresh_interval`](https://www.elastic.co/guide/en/elasticsearch/reference/5.3/index-modules.html#dynamic-index-settings "Dynamic index settingsedit")_ 是 1s，它将强制 _Elasticsearch_ 每秒创建一个新的 _segment_ ，增加这个值（比如 30s），允许生成较大的 _segment_ 再刷新，将会减少将来合并的压了。 

## 禁用初始加载的刷新和副本

如果需要一次加载大量的数据，禁用刷新功能和副本通过设置 _`index.refresh_interval`_ 为 `-1` 并且设置 _`index.number_of_replicas`_ 为 `0`。 这将暂时使您的索引处于风险之中，因为丢失任何_ shard（分片）_会导致数据丢失，但与此同时索引的更快，因为文档将仅被索引一次。一旦初始化加载完成，就可以把 _`index.refresh_interval`_ 和_ `index.number_of_replicas` _改回正常值。

## 禁用swapping

通过禁用交换分区来确保操作系统没有交换出java进程。

## 给文件系统缓存提供内存

文件系统缓存将用于缓冲 I / O 操作。 您应该确保至少将运行 _Elasticsearch_ 的机器内存的至少一半提供给文件系统缓存。

## 使用自动生成的id

当索引一个带有 _id_ 的 _document （文档）_时，_Elasticsearch_ 要检查在相同的 _shard（分片）_上是否还有相同 _id_ 的 _document （文档）_存在，这个操作需要的花费很大，随着索引的增长操作需要的花费将会越来越大。通过使用自动生成的_id_，_Elasticsearch_ 可以跳过此检查，这使索引更快。

## 使用更快的硬件

如果索引受限于 _**I/O**_ ，应该增加文件系统缓存的内存（见上文）或者购买更快的驱动设备。特别是 _**SDD**_ 硬盘比普通硬盘性能更好。通常数据存储在本地，避免使用 **_NFS & SMB_** 等远程文件系统。还要小心虚拟化存储，像亚马逊的 _弹性块存储_（_Elastic Block Storage_）。**Elasticsearch** 在虚拟存储上也有比较好的性能，具有搜索快，安装便捷的特性；然而相对于本地专用存储，他就要慢的多了。如果你在 _**EBS**_上使用 _index ，_一定要使用 _IOPS_ 否则操作会很快挂掉。

通过配置RAID 0阵列，将您的索引分离到多个** _SSD_ **。但是，这将增加失败的风险，因为任何一个 _**SSD**_ 的失败都将破坏这个索引。然而，权衡之后做出如下策略：优化单个分片以实现最佳性能，然后在不同节点之间添加副本，以便任何节点故障都有冗余。您还可以使用快照和还原来备份索引进行进一步的保险。

## 索引缓冲区大小

如果您的节点仅进行大量索引，请确保 **_indices.memory.index_buffer_size_** 足够大，以至于每个 _shard（分片）_最多可以为 512 MB 索引缓冲区进行大量索引（超出索引性能通常不会改善）。_Elasticsearch_ 采用该设置（java堆的百分比或绝对的字节大小），并将其用作所有活动 _shard（分片）_的共享缓冲区。非常活跃的 _shard（分片）_自然会使用这个缓冲区，而不是执行少量索引的 _shard（分片）_。 

通常这个默认值为10％，已经非常富余了：例如，如果给予JVM 10GB内存，则它将向索引缓冲区提供1GB，这足够两个大量索引的 _shard（分片）_。

## 额外优化

调整磁盘使用的策略，也能提高索引的速率。