2016-06-04 9 views
0

Jetzt verwende ich ES, um Aggregation zu tun. Die Grundlogik kann durch Schlüssel mit COUNT (*)> c ) z und hier alsSo optimieren Sie die Aggregationsabfrage in elasticsearch

select count(*) 
from 
(select key, count(*) from table where *** 

Gruppe ausgedrückt werden, die in der Filterbedingung durch Endbenutzer festgelegt ist, was bedeutet, I keine Pre-Arbeit tun . Und ich habe die Logik mit Eimer-Selektor implementiert.

In meinem Fall gibt es jedoch normalerweise mehrere Millionen unterschiedliche Schlüssel, was bedeutet, dass mehrere Millionen Buckets von ES zurückgegeben werden, sortiert nach ihrem doc_count standardmäßig. Und das ist sehr zeitaufwendig. Ich weiß nicht, ob es einige Strategien gibt, die die Abfrage beschleunigen können, zB die Sortierung abschalten.

Antwort

1

Wenn ich richtig verstehe, Ihre Frage ist wie folgt vorgehen:

  1. Gruppe alle Einträge von key
  2. Entfernen Sie alle gruppierten Einträge, bei denen count <= c
  3. Count alle verbleibenden gruppiert Einträge

Dann ist die SELECT key, count(*) nutzlos, weil sie nie wieder benutzt wird. Sie können einfach SELECT 1 verwenden.

Die Sortierung wird für diese Abfrage überhaupt nicht benötigt.


Grundsätzlich gibt es drei Möglichkeiten, um diese Abfrage zu beschleunigen:

  1. mehr Server erhalten! Diese Aggregation kann von ES auf mehreren Knoten einfach parallel ausgeführt werden.

  2. Aggregieren Sie die Daten nicht bei Bedarf, sondern verwenden Sie eine Hintergrundaufgabe, die einmal am Tag ausgeführt wird. Diese Hintergrundaufgabe erstellt im Grunde die gleichen Daten wie Sie unten in STORE 2 sehen können. Natürlich müssen Sie auf diese Weise immer alte Daten liefern, aber es wird die Dinge beschleunigen!

  3. Vorabaggregieren Sie Ihre Daten! Verwenden Sie einige einfache Key-Wertspeicherung (oder vielleicht sogar nur Stick mit ES für diese Operation) und dann wie folgt vorgehen:

    • Wenn ein neues Dokument eingefügt zu werden: Get seine Schlüssel, und die Zahl erhöhen.

    • Wenn ein Dokument gelöscht wird: Ermitteln Sie den Schlüssel und dekrementieren Sie den Zähler.

Dann haben Sie im Grunde zwei Läden: 1 für die tatsächlichen Dokumente, und 1 für die aggregierten Daten, dh

STORE 1: 
[ 
    {id: 1, key: foo, ...}, 
    {id: 2, key: foo, ...}, 
    {id: 3, key: bar, ...}, 
    {id: 4, key: baz, ...} 
] 

STORE 2: 
[ 
    {id: foo, counter: 2}, 
    {id: bar, counter: 1}, 
    {id: baz, counter: 1} 
] 

Auf diese Weise kann die Aggregation zu tun, während die Dokumente Einfügen/Löschen von STORE 1. Dies ist natürlich zeitaufwändiger beim Einfügen/Löschen, da Sie jedes Mal 2 Datenspeicher berühren müssen.

Aber jetzt können Sie einfach die Einträge von STORE 2 zählen, um Ihr Ergebnis zu erhalten. Dies wird die Abfrageleistung für diese Operation enorm steigern.


Sie sehen: Es ist immer ein Kompromiss. Du musst entscheiden, was Sie brauchen:

  1. Live-Daten + hohe Einfügen/Löschen Performance + langsam Aggregation

  2. Nicht-Live-Daten + hohe Einfügen/Löschen Performance + schnelle Aggregation

  3. Live-Daten + langsam einfügen/löschen + schnelle Aggregation

+0

danke für Ihre Antwort. Aber ich habe vergessen zu erwähnen, dass der Benutzer immer einige Filterbedingungen in seiner Abfrage hinzufügen wird. Vor der Aggregation muss ich also etwas filtern, was die Voraggregation nicht sinnvoll macht. Noch viel Dank – shuangshui

Verwandte Themen