Elasticsearch深度分页问题以及Scroll查询的一些总结

背景介绍

我们在 Elasticsearch API的基础上实现了一个日志查询系统,支持最基本的时间范围选择以及关键词搜索高亮,并且日志展示的表格支持异步分页。

有天用户反馈,查询的时候页面报错

Result window is too large, from + size must be less than or equal to: [10000] but was [24600]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting.

这是因为我们的异步分页查询逻辑中使用了 from + size,而 Elasticsearch 默认配置为

“max_result_window”: “10000”

于是, 将这个参数调至 30000, 问题暂时解决。

不过,今天又接到反馈,API报错

Result window is too large, from + size must be less than or equal to: [30000] but was [44600]. See the scroll api for a more efficient way to request large data sets. This limit can be set by changing the [index.max_result_window] index level setting.

一味调整 max_result_window 不是个办法,遂计划详细了解下 window 查询的逻辑,以及 max_result_window 这个参数存在的意义。

Elasticsearch Search 搜索

我们的查询DSL大致如下:

{
    "from": m,
    "size": n,
    "sort": [{"l": "asc"}, {"line": "asc"}],
    "query": {}
}

ES的 Search 搜索是分两个阶段进行的,即Query和Fetch阶段。

Query 阶段

  1. 每个 Shard 通过查询倒排索引,获取满足查询结果的有序文档ID优先队列,队列长度为 from + size
  2. 每个 Shard 返回有序文档列表发送给协调节点,协调节点把所有 Shard 的结果合并产生一个全局排序后的优先队列,队列长度为 from + size

Fetch 阶段

  1. 根据 Query 阶段返回的结果队列决定哪些文档需要被取回,在长度为 from + size 的队列中,前from个文档会被丢弃,只有最后size个文档需要被取回,而这些文档可能来自于一个或者多个分片
  2. 协调节点给相关文档的分片创建一个 Multi Get 请求,一旦所有文档被取回,协调节点返回结果给客户端。

max_result_window 参数的意义

在 Query 阶段中,协调节点需要在长度为 number_of_shard * (from + size) 的排序文档中,找到包含在 size 中的文档。

这个性能,取决于文档大小/分片个数以及硬件性能等,当 from 值足够大时,这个过程会变得沉重,消耗大量的资源,这也是 Elasticsearch 不推荐使用深度分页以及 max_result_window存在的意义。

Elasticsearch Scroll 搜索

在了解深度分页的过程中,看见推荐使用 Scroll 完成深度分页,于是同时了解了一下 Scroll 查询

Scrolling is not intended for real time user requests, but rather for processing large amounts of data, e.g. in order to reindex the contents of one index into a new index with a different configuration.

首先,Scroll 并不适合用来做实时搜索,更适用于大规模数据处理,例如 reindex

Scroll 的使用也分为两个阶段,初始化和遍历。

初始化时将所有符合搜索条件的搜索结果文档ID缓存起来, 形成快照,遍历时直接从快照取数据。

初始化会返回一个 scroll_id,每次遍历时都带上这个id,重复遍历知道返回的数据为空,删除快照。

总结:

Search 相比将Query阶段的队列缓存起来,多次查询时减少 Query阶段的操作,以提高性能?(待继续验证)

Reference

  1. 使用scroll实现Elasticsearch数据遍历和深度分页
  2. Elasticsearch 5.x from size, scroll 和 search after

你可能感兴趣的:(Elastic)