Elasticsearch 2.1:结果窗口太大(index.max_result_window)

af7jpaap  于 2023-05-06  发布在  ElasticSearch
关注(0)|答案(8)|浏览(301)

我们从Elasticsearch 2.1中检索信息,并允许用户浏览结果。当用户请求一个高页码时,我们会得到以下错误消息:
结果窗口太大,from + size必须小于或等于:[10000]但[10020]。请参阅scroll API以获得更有效的方法来请求大型数据集。可以通过更改[index.max_result_window]索引级别参数来设置此限制
弹性文档说这是因为内存消耗高,并使用滚动API:
如果值大于,则每次搜索和执行搜索的每个分片都会消耗大量堆内存块。最安全的做法是保留此值,因为它是用于任何深度滚动的滚动APIhttps://www.elastic.co/guide/en/elasticsearch/reference/2.x/breaking_21_search_changes.html#_from_size_limits
问题是我不想检索大型数据集。我只想从数据集中检索一个切片,它在结果集中的位置非常高。scrolling docu也说:
滚动不适用于真实的用户请求https://www.elastic.co/guide/en/elasticsearch/reference/2.2/search-request-scroll.html
这给我留下了一些问题:
1)如果我使用滚动API向上滚动到结果10020(忽略10000以下的所有内容),而不是对结果10000-10020执行“正常”搜索请求,内存消耗真的会更低吗?
2)看起来滚动API对我来说不是一个选项,而是我必须增加“index.max_result_window”。有人有这方面的经验吗?
3)是否有其他选择来解决我的问题?

6qqygrtg

6qqygrtg1#

如果需要深度分页,一个可能的解决方案是增加max_result_window的值。您可以使用curl从shell命令行执行此操作:

curl -XPUT "http://localhost:9200/my_index/_settings" -H 'Content-Type: application/json' -d '{ "index" : { "max_result_window" : 500000 } }'

对于~ 100 k的值,我没有注意到内存使用量增加。

6yt4nkrj

6yt4nkrj2#

正确的解决方案是使用滚动条。
但是,如果你想将search返回的结果扩展到超过10,000个结果,你可以使用Kibana轻松做到这一点:
转到Dev Tools并将以下内容发布到您的索引(your_index_name),指定新的最大结果窗口

PUT your_index_name/_settings
{ 
  "max_result_window" : 500000 
}

如果一切顺利,您应该会看到以下成功响应:

{
  "acknowledged": true
}
oo7oh9g9

oo7oh9g93#

以下弹性文档中的页面讨论了深度分页:
https://www.elastic.co/guide/en/elasticsearch/guide/current/pagination.htmlhttps://www.elastic.co/guide/en/elasticsearch/guide/current/_fetch_phase.html
根据文档的大小、分片的数量和所使用的硬件,分页10,000到50,000个结果(1,000到5,000页)应该是完全可行的。但是对于足够大的from值,排序过程可能会变得非常繁重,使用大量的CPU、内存和带宽。因此,我们强烈建议不要使用深度分页。

eivgtgni

eivgtgni4#

使用Scroll API获得超过10000个结果。
Scroll example in ElasticSearch NEST API
我是这样使用它的:

private static Customer[] GetCustomers(IElasticClient elasticClient)
{
    var customers = new List<Customer>();
    var searchResult = elasticClient.Search<Customer>(s => s.Index(IndexAlias.ForCustomers())
                          .Size(10000).SearchType(SearchType.Scan).Scroll("1m"));

    do
    {
        var result = searchResult;
        searchResult = elasticClient.Scroll<Customer>("1m", result.ScrollId);
        customers.AddRange(searchResult.Documents);
    } while (searchResult.IsValid && searchResult.Documents.Any());

    return customers.ToArray();
}
kuhbmx9i

kuhbmx9i5#

如果你想要超过10000个结果,那么在所有的数据节点中,内存的使用将非常高,因为它必须在每个查询请求中返回更多的结果。然后,如果你有更多的数据和更多的碎片,那么合并这些结果将是低效的。es还缓存过滤器上下文,因此再次获得更多内存。你必须反复试验你到底服用了多少。如果你在小窗口中收到很多请求,你应该对超过10k的请求进行多个查询,并在代码中自己合并它,这应该比增加窗口大小占用更少的应用程序内存。

umuewwlo

umuewwlo6#

2)看起来滚动API对我来说不是一个选项,而是我必须增加“index.max_result_window”。有人有这方面的经验吗?
--〉您可以在索引模板中定义此值,es template将仅适用于新索引,因此您必须在创建模板后删除旧索引或等待elasticsearch中摄取新数据。
{“order”:1,“template”:“index_template*",“settings”:{“index.number_of_replicas”:“0”,“index.number_of_shards”:“1”,“index.max_result_window”:2147483647 },

jw5wzhpr

jw5wzhpr7#

在我的例子中,看起来通过from & size前缀减少查询的结果将删 debugging 误,因为我们不需要所有的结果:

GET widgets_development/_search
{
  "from" : 0, 
  "size": 5,
  "query": {
    "bool": {}
  },
  "sort": {
    "col_one": "asc"
  }
}
1rhkuytd

1rhkuytd8#

尽管答案提到 * 滚动 * 是正确的解决方案,但在以后的版本中不再是这样了:
我们不再推荐使用scroll API进行深度分页。如果需要在分页超过10,000个命中时保留索引状态,请使用带有时间点(PIT)的search_after参数。

    • 分页搜索结果 滚动搜索结果 *

相关问题