Elasticsearch 2.1: Ergebnisfenster ist zu groß (index.max_result_window)

84

Wir rufen Informationen aus Elasticsearch 2.1 ab und ermöglichen dem Benutzer, durch die Ergebnisse zu blättern. Wenn der Benutzer eine hohe Seitenzahl anfordert, wird die folgende Fehlermeldung angezeigt:

Das Ergebnisfenster ist zu groß. Die Größe + muss kleiner oder gleich: [10000] sein, war aber [10020]. In der Bildlauf-API finden Sie eine effizientere Möglichkeit, große Datenmengen anzufordern. Diese Grenze kann durch Ändern des Indexebenenparameters [index.max_result_window] festgelegt werden

Das elastische Dokument besagt, dass dies auf einen hohen Speicherverbrauch und die Verwendung der Bildlauf-API zurückzuführen ist:

Werte, die höher sind, als pro Suche und pro Shard, der die Suche ausführt, erhebliche Teile des Heapspeichers verbrauchen können. Es ist am sichersten, diesen Wert zu belassen, da die Scroll-API für tiefes Scrollen verwendet wird. Https://www.elastic.co/guide/en/elasticsearch/reference/2.x/breaking_21_search_changes.html#_from_size_limits

Die Sache ist, dass ich keine großen Datenmengen abrufen möchte. Ich möchte nur ein Slice aus dem Datensatz abrufen, das sehr hoch in der Ergebnismenge ist. Auch das Scrolling-Dokument sagt:

Das Scrollen ist nicht für Benutzeranfragen in Echtzeit vorgesehen. Https://www.elastic.co/guide/en/elasticsearch/reference/2.2/search-request-scroll.html

Dies lässt mich einige Fragen offen:

1) Wäre der Speicherverbrauch wirklich geringer (wenn ja, warum), wenn ich die Bildlauf-API verwende, um zum Ergebnis 10020 zu scrollen (und alles unter 10000 zu ignorieren), anstatt eine "normale" Suchanforderung für das Ergebnis 10000-10020 durchzuführen?

2) Es scheint nicht, dass die Bildlauf-API eine Option für mich ist, sondern dass ich "index.max_result_window" erhöhen muss. Hat jemand irgendwelche Erfahrungen damit?

3) Gibt es andere Möglichkeiten, um mein Problem zu lösen?

Ronald
quelle

Antworten:

76

Wenn Sie eine tiefe Paginierung benötigen, besteht eine mögliche Lösung darin, den Wert zu erhöhen max_result_window. Sie können curldies über Ihre Shell-Befehlszeile tun:

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

Ich habe keine erhöhte Speichernutzung für Werte von ~ 100k bemerkt.

Andrey Morozov
quelle
Ich habe den gleichen Fehler 'Result window is too large, from + size must be less than or equal to: [10000] but was [47190]. 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 parameter.')Es sagte, es hat 4719 Seiten (jede Seite 10 Ergebnisse). und ich denke, Ihr Vorschlag funktioniert.
Dotslash
1
Dies ist eine gute Lösung für kleine Mengen von Dokumenten unter 500000
Ezzat
2
Ich verwende ES v2.2.0 und musste die Nutzlast auf ändern, { "max_result_window" : 500000 }damit dies funktioniert. So wurde der Curl-Befehl -curl -XPUT "http://localhost:9200/my_index/_settings" -d '{ "max_result_window" : 500000 }'
Parin Porecha
3
Für diejenigen, die mit diesem Befehl einen Headerfehler für eine neuere Version von elasticsearch erhalten, müssen Sie auch den Header übergeben. curl -XPUT " localhost: 9200 / my_index / _settings " -H "Inhaltstyp: application / json" -d '{ "index": {"max_result_window": 50000}} '
Satys
30

Die richtige Lösung wäre das Scrollen.
Wenn Sie jedoch die Ergebnisse erweitern möchtensearch über 10.000 Ergebnisse hinaus , können Sie dies problemlos mit Kibana tun:

Gehen Sie zu Dev Toolsund veröffentlichen Sie einfach Folgendes in Ihrem Index (Ihr_Indexname), und geben Sie an, was das neue Fenster mit den maximalen Ergebnissen sein soll

Geben Sie hier die Bildbeschreibung ein

PUT your_index_name/_settings
{ 
  "max_result_window" : 500000 
}

Wenn alles gut geht, sollten Sie die folgende Erfolgsreaktion sehen:

{
  "acknowledged": true
}
Guy Dubrovski
quelle
1
Ich habe versucht, dies im Elasticsearch-Code (put_settings etc ..) zu tun, und bin auf viele Fehler gestoßen. Das spart mir Stunden! Danke dir!
cpres
23

Die folgenden Seiten in der elastischen Dokumentation befassen sich mit Deep Paging:

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

Abhängig von der Größe Ihrer Dokumente, der Anzahl der Shards und der von Ihnen verwendeten Hardware sollte es durchaus möglich sein, 10.000 bis 50.000 Ergebnisse (1.000 bis 5.000 Seiten) tief zu pagen. Bei ausreichend großen Werten kann der Sortierprozess jedoch sehr umfangreich werden, da große Mengen an CPU, Speicher und Bandbreite benötigt werden. Aus diesem Grund raten wir dringend von einem tiefen Paging ab.

Ronald
quelle
1
Also sollten wir hier die tiefe Paginierung aufgeben, oder? Grundsätzlich bedeutet es nicht, 4000 Seiten für einen einzelnen Betrachter zu blättern. Nehmen wir an, Google-Suche, kaum scrollen wir zu Seite 8 oder 9, um die Ergebnisse zu überprüfen. Normalerweise kümmern wir uns nur um die obersten 3-5 Seiten, die Google uns zur Verfügung stellt.
Dotslash
2
Können wir die Scroll-API verwenden, falls wir eine tiefe Paginierung benötigen?
Abhi.G
3
Wenn wir jedoch die Sortierfunktion aktivieren, beispielsweise auf einer E-Commerce-Website. wenn Benutzer Artikel mit dem höchsten Preis sehen möchten. Das Ergebnis ist anders, wenn wir nach dem höchsten Preis sortieren, als wenn wir nach der niedrigsten Seite sortieren, aber zur letzten Seite gehen, oder? da wir die Anzahl der Ergebnisse begrenzen, kann darauf zugegriffen werden. Gibt es eine Lösung dafür?
MR Murazza
3

Verwenden Sie die Scroll-API, um mehr als 10000 Ergebnisse zu erhalten.

Beispiel für einen Bildlauf in der ElasticSearch NEST-API

Ich habe es so benutzt:

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();
}
Morten Holmgaard
quelle
0

Wenn Sie mehr als 10000 Ergebnisse wünschen, ist die Speichernutzung in allen Datenknoten sehr hoch, da bei jeder Abfrageanforderung mehr Ergebnisse zurückgegeben werden müssen. Wenn Sie dann mehr Daten und mehr Shards haben, ist das Zusammenführen dieser Ergebnisse ineffizient. Außerdem wird der Filterkontext zwischengespeichert, daher wieder mehr Speicher. Sie müssen versuchen, wie viel genau Sie nehmen. Wenn Sie viele Anfragen in einem kleinen Fenster erhalten, sollten Sie mehrere Abfragen für mehr als 10.000 durchführen und diese selbst im Code zusammenführen, der weniger Anwendungsspeicher beanspruchen soll, als wenn Sie die Fenstergröße erhöhen.

Amritendu
quelle
0

2) Es scheint nicht, dass die Bildlauf-API eine Option für mich ist, sondern dass ich "index.max_result_window" erhöhen muss. Hat jemand irgendwelche Erfahrungen damit?

-> Sie können diesen Wert in Indexvorlagen definieren. Diese Vorlage gilt nur für neue Indizes. Sie müssen also entweder alte Indizes nach dem Erstellen der Vorlage löschen oder warten, bis neue Daten in elasticsearch aufgenommen werden.

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

Sindhu
quelle
0

In meinem Fall sieht es so aus, als würde das Reduzieren der Ergebnisse über die Präfixe from & size auf die Abfrage den Fehler beseitigen, da wir nicht alle Ergebnisse benötigen:

GET widgets_development/_search
{
  "from" : 0, 
  "size": 5,
  "query": {
    "bool": {}
  },
  "sort": {
    "col_one": "asc"
  }
}
FlimFlam Vir
quelle