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

105

我们从Elasticsearch 2.1中检索信息,并允许用户浏览结果。当用户请求高页码时,我们会收到以下错误消息:

结果窗口太大,from + size必须小于或等于[10000],但实际为[10020]。请参见滚动API以请求大型数据集的更有效方式。可以通过更改[index.max_result_window]索引级参数来设置此限制

Elastic文档表示,这是由于内存消耗过高,需要使用滚动API:

比此值更高的值可能会消耗每个搜索和执行搜索的分片的堆内存的重要块。最安全的方法是将此值保持不变,并对任何深度滚动使用滚动API https://www.elastic.co/guide/en/elasticsearch/reference/2.x/breaking_21_search_changes.html#_from_size_limits

问题在于,我不想检索大型数据集。我只想检索结果集中非常靠前的一部分数据。此外,滚动文档指出:

滚动条不适用于实时用户请求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)是否有其他解决我的问题的选择?
9个回答

89
如果您需要深度分页,一个可能的解决方案是增加 max_result_window 的值。 您可以使用 curl 命令从 shell 命令行完成此操作:
curl -XPUT "http://localhost:9200/my_index/_settings" -H 'Content-Type: application/json' -d '{ "index" : { "max_result_window" : 500000 } }'

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


我遇到了与您相同的错误:“结果窗口太大,从+大小必须小于或等于:[10000]但是实际为[47190]。请参阅滚动API以获取请求大型数据集的更有效方法。可以通过更改[index.max_result_window]索引级别参数来设置此限制。”它显示了4719页(每页10个结果),而我认为您的建议可行。 - dotslash
2
这是一个适用于小于500000份文档的良好解决方案。 - Ezzat
2
我正在使用ES v2.2.0,我不得不将有效载荷更改为{ "max_result_window" : 500000 }才能使其工作。因此,curl命令变成了- curl -XPUT“http://localhost:9200/my_index/_settings” -d '{ "max_result_window" : 500000 }' - Parin Porecha
3
针对更新版本的Elasticsearch,在执行此命令时,如果出现标题错误,需要同时传递标题。命令如下:curl -XPUT "http://localhost:9200/my_index/_settings" -H "Content-Type: application/json" -d '{"index":{"max_result_window":50000}}'。 - Satys

45

最好的解决方案是使用滚动。
但是,如果您想将搜索返回结果扩展到10,000个以上,您可以使用Kibana轻松完成:

转到Dev工具并将以下内容发布到您的索引(your_index_name),指定将会是新的最大结果窗口。

输入图像描述

PUT your_index_name/_settings
{ 
  "max_result_window" : 500000 
}

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

{
  "acknowledged": true
}

2
我尝试按照elasticsearch代码中的方法(put_settings等)进行操作,但遇到了许多错误。这节省了我好几个小时!谢谢! - cpres
通过 GET your_index_name/_settings 命令,您可以获取当前的设置。 - Silvan

30
以下是弹性文档中关于深度分页的页面链接:

https://www.elastic.co/guide/en/elasticsearch/guide/current/pagination.html https://www.elastic.co/guide/en/elasticsearch/guide/current/_fetch_phase.html

根据您的文档大小、碎片数量和所使用的硬件,浏览10,000到50,000个结果(即1,000到5,000页)是完全可行的。但如果from值足够大,则排序过程可能会变得非常耗费资源,使用大量的CPU、内存和带宽。因此,我们强烈建议不要进行深度分页。

1
所以在这里,我们应该放弃深度分页,对吧?基本上,为单个查看者分页4000页没有任何意义。比如说,Google搜索,我们几乎不会滚动到第8或9页来检查结果。通常我们只关心Google给我们的前3-5页。 - dotslash
2
我们在需要深度分页的情况下可以使用滚动API吗? - Abhi.G
3
当我们在电商网站上启用排序功能时,比如用户想查看最高价格的商品。当我们按最高价格排序时,结果将与按最低价格排序并跳转到最后一页不同,因为我们限制了可以访问的结果数量。有没有解决这个问题的方法? - M.R. Murazza
有时用户会导航到结果的“最后”一页,如果那是第4000页,那就是了。 我希望有比滚动更好的解决方案,因为如果您正在获取集合中的特定页面,则滚动非常基本且没有太多用途。 - ChristoKiwi

3
使用Scroll API获取超过10000个结果。
这是一个关于ElasticSearch NEST API中滚动查询的例子,具体内容请参考链接: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();
}

0

2) 看起来滚动 API 对我不适用,但我必须增加 "index.max_result_window"。有人有这方面的经验吗?

--> 您可以在索引模板中定义此值,es 模板仅适用于新索引,因此您必须在创建模板后删除旧索引或等待将新数据摄入 Elasticsearch。

{ "order": 1, "template": "index_template*", "settings": { "index.number_of_replicas": "0", "index.number_of_shards": "1", "index.max_result_window": 2147483647 },


0

如果您想要超过10000个结果,那么在所有数据节点中,内存使用量将非常高,因为每个查询请求都需要返回更多的结果。然后,如果您有更多的数据和更多的分片,那么合并这些结果将是低效的。另外,es会缓存过滤器上下文,因此会再次增加内存使用量。您必须试错,确定实际需要的内存大小。如果您在短时间内接收到许多请求,您应该执行多个大于10k的查询,并在代码中自行合并,这样比增加窗口大小所需的应用程序内存少。


0

尽管有答案提到滚动是正确的解决方案,但在后续版本中不再是这样:

我们不再建议使用滚动API进行深度分页。如果您需要在浏览超过10,000个命中时保留索引状态,请使用带有时间点(PIT)的search_after参数。

分页搜索结果 > 滚动搜索结果


0
在我的情况下,通过使用 from 和 size 前缀来减少查询结果似乎可以消除错误,因为我们不需要所有的结果。
GET widgets_development/_search
{
  "from" : 0, 
  "size": 5,
  "query": {
    "bool": {}
  },
  "sort": {
    "col_one": "asc"
  }
}

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接