如何提高我的 Elasticsearch 集群上的索引性能?

上次更新时间:2019 年 8 月 23 日

我想要优化 Amazon Elasticsearch Service (Amazon ES) 中的索引操作,以便可以获得最大的提取吞吐量。

解决方法

使用以下方法中的一个或多个提高 Amazon ES 中的集群的索引性能。

确保您正在提取的索引的分区均匀分布在数据节点中

使用以下公式来确认该分片均匀分布:

索引的分区数 = k *(数据节点数量),其中 k 是每个节点的分区数量

例如,如果索引中有 24 个分区且有八个数据节点,每个节点应有三个分区。有关更多信息,请参阅开始使用 Amazon Elasticsearch Service:我需要多少个分区?

将 refresh_interval 提高到 60 秒或以上

刷新您的 Elasticsearch 索引会使您的文档可用于搜索。虽然这是轻量级操作,但刷新您的索引需要索引线程以其他方式使用的资源。

默认刷新间隔为一秒。当您提高刷新间隔时,数据节点会进行较少的 API 调用。刷新间隔越长,索引速度越快。提高刷新间隔还有助于防止 429 错误

将副本数量更改为零

如果您预测有一个小时或两个小时的繁重索引,则考虑将 index.number_of_replicas 设置为 0。每个副本都会重复索引过程,因此,禁用副本可提高性能。当索引结束时,再次启用副本。

重要提示:如果某个节点在副本被禁用时发生故障,您可能会失去数据。只有当您可以忍受一个或两个小时的数据丢失时,才能禁用副本。

找到最佳批量请求大小的实验

从 5–15 MiB 的批量请求大小开始。然后,缓慢增加请求大小,直到索引性能停止改进。有关更多信息,请参阅 Elasticsearch 文档中的使用并调整批量请求大小

注意:有些实例类型将批量请求限制为 10 MiB。有关更多信息,请参阅网络限制

使用具有 SSD 实例存储卷(如 I3)的实例类型

I3 实例可提供本地快速非易失性内存表达 (NVMe) 存储。这些实例提供的提取性能显著高于使用通用型 SSD (gp2) Amazon Elastic Block Store (Amazon EBS) 卷的实例。有关更多信息,请参阅使用 I3 实例在 Amazon Elasticsearch Service 上运行 PB 级集群

缩小响应大小

要缩小 Elasticsearch 响应的大小,请使用 filter_path 参数排除您不需要的字段。请确保您没有筛选掉识别或重试失败请求所需的字段。这些字段因客户端而不同。

在以下示例中,index-name、type-name took 字段被排除在响应之外:

curl -X POST "es-endpoint/index-name/type-name/_bulk?pretty&filter_path=-took,-items.index._index,-items.index._type" -H 'Content-Type: application/json' -d'
{ "index" : { "_index" : "test2", "_id" : "1" } }
{ "user" : "testuser" }
{ "update" : {"_id" : "1", "_index" : "test2"} }
{ "doc" : {"user" : "example"} }

有关更多信息,请参阅缩小响应大小

提高 index.translog.flush_threshold_size 的值

默认情况下,index.translog.flush_threshold_size 被设置为 512 MB。这表示当 translog 达到 512 MB 时会被刷新。索引负载越繁重,translog 刷新就越频繁。当您提高 index.translog.flush_threshold_size 时,节点执行此开销大的操作的频率较低。这通常会提高索引性能。提高大小的另一个益处在于,集群会创建几个大型分段,而不是多个小型分段。大型分段的合并频率较低,这意味着更多的线程将用于索引而不是合并。

提高 index.translog.flush_threshold_size 的缺点在于,translog 刷新需要更长时间。如果某个分区失败,由于 translog 较大,恢复需要的时间更长。

提高 index.translog.flush_threshold_size 之前,调用以下 API 操作来获取当前刷新操作的统计数据。替换示例中的以下值:

  • es-endpoint:您的 Elasticsearch 集群终端节点
  • index-name:索引名称
$ curl 'es-endpoint/index-name/_stats/flush?pretty'

在输出中,记下刷新次数和总时间。以下示例中进行了 124 次刷新,耗费时间 17690 毫秒:

"flush" { "total" : 124, "total_time_in_millis" : 17690 }

要增加刷新阈值大小,请调用以下 API 操作。在此示例中,刷新阈值大小设置为 1024 MB,这非常适合内存超过 32 GB 的实例。选择最适合您的使用案例的阈值大小。

$ curl -XPUT 'es-endpoint/index-name/_settings?pretty' -d '{"index":{"translog.flush_threshold_size" : "1024MB"}}'

再次运行 _stats API 操作以查看刷新活动的变化情况:

$ curl 'es-endpoint/index-name/_stats/flush?pretty' 

注意:最佳做法是首先只增加当前索引的 index.translog.flush_threshold_size。在您确认获得所需的结果后,将这些更改应用于索引模板。

禁用 _all 字段

_all 字段将所有其他字段的值都串联到一个字符串中。它需要的 CPU 和磁盘空间比其他字段更多。大多数使用案例不需要 _all 字段。您可以使用 copy_to 参数串联多个字段。

在 Elasticsearch 版本 6.0 和更高版本中,_all 字段默认禁用。要在早期版本中禁用 _all 字段,将已启用设置为 false。例如:

curl -XPUT  <es-endpoint>/<index-name>?pretty -d '{"mappings" : {"type-name" : {"_all": {"enabled": false}}}}' -H 'Content-Type: application/json'

除了禁用 _all 字段外,您还可以精简 _source 字段。此操作仅建议高级用户使用。有关更多信息,请参阅 Elasticsearch 文档中的 _source field


这篇文章对您有帮助吗?

我们可以改进什么?


需要更多帮助吗?