Skip to content

Latest commit

 

History

History
151 lines (90 loc) · 12.1 KB

优化更新.md

File metadata and controls

151 lines (90 loc) · 12.1 KB

写入优化

如果是集群首次灌入数据,可以将副本数设置为0,写入完毕再调整回去,这样副本分片只需要拷贝,节省了索引过程/如果要进行大量批量导入,请考虑通过设置index.number_of_replicas来禁用副本:0。

主要原因在于:复制文档时,将整个文档发送到副本节点,并逐字重复索引过程。这意味着每个副本都将执行分析,索引和潜在合并过程

相反,如果使用零副本进行索引,然后在提取完成时启用副本,则恢复过程本质上是逐字节的网络传输。 这比复制索引过程更有效。

参考链接:


refresh_interval

设置刷新时间

PUT /ag_advertisement_test/_settings
{
    "index" : {
        "refresh_interval" : "-1"
    }
}

设置后,更新并不能通过_search是获取到最新的数据,

但是如果:直接去获取单个文档的数据GET ag_advertisement_test/data/1000003?parent=1900d3a59d00c93b26678287e6df0185), 会发现最新的数据.并且发现_search的部分数据已经刷新到最新

而且如果再次再次更新单个文档的, 会把旧的版本刷新到可搜素,但仍不是最新的,而且也发现_search的部分数据已经刷新到最新

原因见事务日志的作用


亚马逊的建议

分片的一般大小推荐为:30G

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

  • 将 refresh_interval 提高到 60 秒或以上

  • 将副本数量更改为零

  • 找到最佳批量请求大小的实验:从 5–15 MiB 的批量请求大小开始。然后,缓慢增加请求大小,直到索引性能停止改进。

  • 缩小响应大小。通过filter_path进行返回信息的缩减。减少网络传输的流量。

  • 提高 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 较大,恢复需要的时间更长。

刷新阈值大小设置为 1024 MB,这非常适合内存超过 32 GB 的实例。选择最适合您的使用案例的阈值大小。

  • 禁用 _all 字段。

参考链接:


段合并

优化点一:降低分段产生的数量 / 频率

  • 可以将 Refresh Interval 调整到分钟级别 /indices.memory.index_buffer_size (默认是 10%)
  • 尽量避免文档的更新操作

优化点二:降低最大分段大小,避免较大的分段继续参与 Merge,节省系统资源。(最终会有多个分段)

  • Index.merge.policy.segments_per_tier,默认为 10, 越小需要越多的合并操作
  • Index.merge.policy.max_merged_segment, 默认 5 GB, 操作此大小以后,就不再参与后续的合并操作。forcemerge 除外。

segment size; bigger segments won’t be merged with other segments. You’d lower this value if you wanted less merging and faster indexing because larger segments are more difficult to merge. elasticsearch-in-action

要注意的是,最新的官方文档有相关的建议:

Force merge should only be called against an index after you have finished writing to it. Force merge can cause very large (>5GB) segments to be produced, and if you continue to write to such an index then the automatic merge policy will never consider these segments for future merges until they mostly consist of deleted documents. This can cause very large segments to remain in the index which can result in increased disk usage and worse search performance.

只有在完成对索引的写入后,才应针对该索引调用强制合并。强制合并可能会导致生成非常大(>5GB)的段,如果继续写入此类索引,则自动合并策略将永远不会考虑将来合并这些段(max_merged_segment参数: 5G),直到它们主要由已删除的文档组成。这会导致索引中保留非常大的段,从而导致磁盘使用率增加和搜索性能降低

经常更新导致segment过大

通过GET /_cat/segments获取到段的大小,可以看到即使没有手动进行段合并,也会因为更新频繁,导致segment的大小超出5G,也会造成性能问题。所以定时的POST /appinfo/_forcemerge?only_expunge_deletes=true还是可行的?但需要月度或者季度进行reindex操作更好,让segment分散?数据量较大则调整分片数目。

Q: 为什么正式环境里面的deleted docs那么多。按理来说正常的merge segment会把deleted docs清空。

A: 通过GET /_cat/segments?index=material*&s=size:desc&v=true可以看到,很多的segment已经得到5G,超过max_merged_segment的限制,所以这些segment不会参与到自动merge过程。而这些segment因为还会被经常更新,导致其deleted docs一直被增加,而无法得到回收?

问题: 手动执行POST /appinfo/_forcemerge?only_expunge_deletes=true会把这些segment合成一个?导致5G+5G这样的大segment么?

A: 不会。因为这个命令也只是执行少于max_merged_segment的segment的合并(应该是大部分由删除文档组成10%的segment)。所以要想完全的没有deleted docs,一个方法是max_num_segments=1,但是如果还会更新操作的话,会导致segment过大而降低性能。

Q: 也就是跟自动merge segment有啥区别?为啥自动的merge不能清理大部分的deleted docs?是因为自动的merge时候segment的选择规则问题?只选择较小的segment进行合并?

A: 如果正在构建的索引中的段数超过了阈值,该策略将先对索引段按容量降序排序(这里考虑了被标记为已删除的文档),然后再选择一个成本最低的合并

A: 选出一定数量的segments来merge。也就是说这次的merge 操作,根据当前segments总的字节数推算,ES应该是被允许最多merge 22 个segments;接着就是去找实际可以merge的总的eligible的segments数量,达不到预期数量,就不做了。

这只是延迟做了?如果后面做Merge是选择所有的segment,就还是可以进行删除文档的清空。还是说只会合并部分的segment呢?

A: index.merge.policy.segments_per_tier: 每层segment数量, 需要>=max_merge_at_once, 否则会发生频繁的merge。应该是该参数限制了大段的合并。导致deleted_doc无法清理。

需要更深入阅读源码合并的具体策略才能搞清楚。目前观察到的场景是: 一直更新自动merge,不会出现过大的超出5G的segment。虽然有些浮动,原因应该是更新导致的(根据文档如果这些segment是有大多数删除文档构成也是会进行合并,得到大于5G的segment的?)。但是如果执行了only_expunge_deletes选项的merge,会有过大的segment,持续执行后,发现了30G以上的segment。因为会选择删除比例是10%的segment进行合并,也不会有5G的限制。还是尽量少用。

强制合并对于管理数据流的旧备份索引和其他基于时间的索引非常有用,特别是在翻滚之后。在这些情况下,每个索引只在一段时间内接收索引流量。一旦索引不再接收写操作,它的碎片就可以强制合并到一个单独的段中。这可能是一个好主意,因为单段分片有时可以使用更简单、更高效的数据结构来执行搜索。

aws

清除已删除的文档

要手动回收磁盘空间,请运行强制合并 API 并将 only_expunge_deletes 参数设置为“true”:

POST /<index-name>/_forcemerge?only_expunge_deletes=true

**注意:**此操作只会清除包含标记为删除的分段。

因此,强制合并将减少使用的磁盘空间量。创建新分段后,旧分段将被移除,新分段将不再包含标记为删除的文档。有关已删除文档的更多信息,请参阅 Elasticsearch 网站上的 Lucene's handling of deleted documents

但是,在执行强制合并操作时,请注意以下几点:

  • 仅当有足够的可用存储空间时,才对 Elasticsearch 集群执行强制合并。此操作属于资源密集型操作。
  • 强制合并操作将触发一个 I/O 密集型进程,并阻止对集群的所有新请求,直到合并完成。
  • 仅当没有其他数据写入索引时,才对只读索引调用强制合并操作。如果针对读/写索引调用强制合并,则该操作会导致生成非常大的分段(每个分段大于 5GB)。发生这种情况时,自动合并策略不会考虑在未来合并这些非常大的分段,除非这些分段主要由已删除的文档组成。因此,磁盘使用量会增加,并且搜索性能会下降。

您还可以使用按查询删除 API删除 API 来手动删除 Elasticsearch 集群中的任何文档。

只有在停写后,主动的强制合并,才适用。不然segment会越来越大,超出max_merged_segment的限制。从而导致磁盘使用率增加和搜索性能降低。

参考链接