2016-02-04 203 views
52

我们从Elasticsearch 2.1中检索信息并允许用户查看结果。当用户请求高页码,我们得到了以下错误消息:Elasticsearch 2.1:结果窗口太大(index.max_result_window)

结果窗口过大,从+大小必须小于或等于 到:[10000]但[10020]。请参阅滚动API以获得更高效的请求大型数据集的方式。此限制可通过改变设置的 [index.max_result_window]索引等级参数

弹性实况说,这是因为高存储器消耗和使用滚动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)有没有其他的选择来解决我的问题?

回答

15

在弹性文档深谈寻呼以下页面:

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页)深度应该是完全可行的。但是从 值来看,分类过程的确会变得非常重要,使用大量的CPU,内存和带宽。出于这个原因,我们强烈建议 针对深度分页。

+0

所以在这里,我们应该放弃深度分页,对吧?基本上,对于单个查看器来说,不存在分页4000页的含义。比方说,谷歌搜索,我们很难滚动到第8或第9页检查结果。通常我们只关注Google给我们的前3-5个页面。 – dotslash

+2

如果我们需要深度分页,我们可以使用滚动API吗? –

+2

但是,当我们启用排序功能时,可以在电子商务网站上说。当用户想要查看价格最高的商品时。当我们按最高价格比较排序时,结果会有所不同,而当我们按最低页面排序时,结果会有所不同,但最后一页是正确的?因为我们限制可以访问的结果的数量。 任何解决此问题的方法? –

55

如果您需要大深分页,我想的解决方案只有一个变种是增加值max_result_window

curl -XPUT "http://localhost:9200/my_index/_settings" -d '{ "index" : { "max_result_window" : 500000 } }' 

内存使用量的增加,我没有发现的〜100K

+0

我有同样的错误结果窗口太大,从+大小必须小于或等于:[10000],但是[47190]。请参阅滚动API以获取更高效的请求大型数据集的方法。这个限制可以通过改变[index.max_result_window]索引级别参数来设置。')它说它有4719页(每页10个结果)。我认为你的建议是有效的。 – dotslash

+0

对于小于500000的少量文档,这是一个很好的解决方案 – Ezzat

+1

我正在使用ES v2.2.0,并且我必须将有效负载更改为“{”max_result_window“:500000}”才能正常工作。所以curl命令变成了 - 'curl -XPUT“http:// localhost:9200/my_index/_settings”-d'{“max_result_window”:500000}'' –

2

使用滚动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(); 
} 
-5

的最主要的原因,您收到此错误 - 这是becouse您使用的是一个错误的方式弹性搜索。 ES是一个搜索引擎。这对于获取数据中的许多元素或许多页面并不有效。也许你正试图通过弹性搜索来操作所有数据,而不仅仅是搜索相关结果?这是不正确的。

所以,你应该使用它进行搜索。而且我认为,没有必要获得超过10000个结果项目。例如,谷歌只返回前1000个结果。

0

如果您想要10000个以上的结果,那么在所有数据节点中,内存使用率将非常高,因为它必须在每个查询请求中返回更多结果。那么如果你有更多的数据和更多的碎片,那么合并这些结果将是低效的。同时es缓存过滤器上下文,因此再次存储更多内存。你必须尝试和错误你正在采取多少。如果您在小窗口中收到很多请求,您应该执行多个查询超过10k并将其自行合并到代码中,如果您增加窗口大小,应该占用更少的应用程序内存。

0

2)似乎没有滚动API是我的选择,但我不得不增加“index.max_result_window”。有人对这个有经验么?

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

{ “顺序”:1, “模板”: “index_template *”, “设置”:{ “index.number_of_replicas”: “0”, “index.number_of_shards”: “1”, “index.max_result_window”:2147483647 },

9

正确的解决方案是使用滚动。
但是,如果你想扩展的结果10,000个以后的结果search回报,你可以很容易地Kibana做到这一点:

转到Dev Tools,只是张贴下面您指数(your_index_name),specifing这将是新的最大结果窗口

enter image description here

PUT your_index_name/_settings 
{ 
    "max_result_window" : 500000 
} 

如果一切顺利的话,你应该看到下面的成功响应:

{ 
    "acknowledged": true 
} 
+1

我尝试了在elasticsearch代码中执行此操作的方式(put_settings等)。并且达到了很多错误。这节省了我的时间!谢谢! – cpres