Platzeinsparungen: Ein weniger bekannter Vorteil der Indexsortierung in Elasticsearch

In Elasticsearch 6.0 haben wir eine neue Funktion mit dem Namen Indexsortierung eingeführt. Der verlinkte Blogeintrag enthält weiterführende Informationen, aber kurz gesagt sortiert diese Funktion Dokumente zum Zeitpunkt der Indizierung nach einem oder mehreren Schlüsseln Ihrer Wahl. Diese Methode hat einige Vorteile, die wir bereits behandelt haben:

  • Wenn Sie von Elasticsearch eine Reihe von Ergebnissen mit demselben Sortierschlüssel wie ein vorhandener Index abfragen, muss Elasticsearch die Ergebnisse zum Zeitpunkt der Abfrage nicht mehr sortieren. Sie sind bereits vorsortiert!
  • Wenn Sie nicht die gesamte Trefferanzahl benötigen und nach dem Sortierschlüssel sortieren, kann Elasticsearch die Abfrage abbrechen, sobald genügend Treffer gefunden wurden. Dieser Vorteil kann die Leistung von Abfragen dramatisch verbessern.
  • Wenn Ihre Abfragen ANDs über verschiedene Felder verwenden, können Sie diese Felder mit der Indexsortierung so gruppieren, dass Elasticsearch große Blöcke nicht übereinstimmender Dokumenten überspringen kann, um die Suche ebenfalls zu beschleunigen.

Kurz gesagt können Sie Ihre Suche mit der Indexsortierung in manchen Fällen beschleunigen, insbesondere dann, wenn Ihre Dokumente auf bestimmte gängige Arten durchsucht und sortiert werden. Vielen Anwendern ist jedoch nicht bewusst, dass sie mit der Indexsortierung auch den Speicherbedarf ihrer Indizes auf der Festplatte reduzieren können. Ich werde Ihnen hier erklären, warum und wie.

Achtung: Indexsortierung ist nur in bestimmten Fällen sinnvoll

Bevor ich weiter auf dieses Thema eingehe, möchte ich erneut betonen, dass sich die Indexsortierung nicht für alle Anwendungsfälle eignet. Sie sorgt dafür, dass die Sortierung zum Zeitpunkt der Indizierung erfolgt. Sortieren ist ein aufwändiger Vorgang, daher sollte diese Funktion nur mit Bedacht aktiviert werden, wenn die Indizierungsgeschwindigkeit eine Rolle spielt. Die Schreibleistung kann um bis zu 40-50 % einbrechen. Viele Anwendungsfälle in den Bereichen Logging, Metriken und Sicherheitsanalysen benötigen einen guten Indizierungsdurchsatz und eignen sich daher nicht für die Indexsortierung. Diese Funktion macht unter Umständen Sinn für Sie, wenn Sie eine niedrigere Indizierungsrate haben, wenn die Abfragegeschwindigkeit entscheidend für Ihren Anwendungsfall ist oder wenn Sie sowieso einen Reindizierungsprozess verwenden, der außerhalb der Spitzenzeiten tätig wird.

Analyse möglicher Sortierreihenfolgen: Ein Beispiel

Angenommen, ich verwende eine Elasticsearch-Instanz, die für eine Produktsuche verwendet wird. Stellen Sie sich eine Reihe Dokumente vor, die zum Indizierungszeitpunkt wie folgt aussehen (zur einfacheren Darstellung als Matrix vereinfacht):

Produkt-IDProduktkategorieProduktfarbePreis
206f467b-8cfeSchuheRot$97.00
4f89fbec-acc3JackenSchwarz$120.50
47771396-dfe3JackenGrau$170.10
c6c8fbdf-651bHüteGelb$15.00
dc18c426-0eb3SchuheRot$107.20
ee304259-df57JackenSchwarz$88.00
9332c0ac-e55eSchuheSchwarz$49.00
30e96765-52a1HüteBlau$11.00
811cc8ca-d6bbJackenBlau$92.99

Nehmen wir außerdem an, wir möchten die Indexsortierung aktivieren. Wonach sollten wir sortieren? Wir haben mehrere Optionen: Produktkategorie, Produktfarbe und/oder Preis sind möglicherweise interessant. Wenn unsere Benutzer ihre Suche fast immer nach dem Preis sortieren und wir keine Filter für Kategorie oder Farbe haben, macht es Sinn, den Preis als Sortierschlüssel zu verwenden. Es ist jedoch wahrscheinlich, dass die Benutzer mindestens eine Kategorie auswählen, bevor die den günstigsten Artikel finden, und dass sie eine bevorzugte Farbe haben. Wir werden also nach Kategorie aufsteigend, Farbe aufsteigend und anschließend nach Preis absteigend sortieren.

"sort.field" : ["product_category", "product_color", "price"], "sort.order" : ["asc", "asc", "asc"]

Der sortierte Index sieht in etwa wie folgt aus:

Produkt-IDProduktkategorieProduktfarbePreis
30e96765-52a1HüteBlau$11.00
c6c8fbdf-651bHüteGelb$15.00
ee304259-df57JackenSchwarz$88.00
4f89fbec-acc3JackenSchwarz$120.50
811cc8ca-d6bbJackenBlau$92.99
47771396-dfe3JackenGrau$170.10
9332c0ac-e55eSchuheSchwarz$49.00
206f467b-8cfeSchuheRot$97.00
dc18c426-0eb3SchuheRot$107.20

Dabei passieren einige interessante Dinge, die ich an einem Beispiel veranschaulichen möchte:

  • Wenn ich mit Elasticsearch nach den zwei günstigsten Schuhen nach Preis sortiert suche und keine Gesamtzahl der Schuhe benötige, sucht das System nach dem Block mit Schuhen und kann dazu praktischerweise alle anderen Kategorien überspringen. Sobald zwei Ergebnisse gefunden wurden, wird die Verarbeitung des Index abgebrochen und das Suchergebnis zurückgegeben. Dazu müssen Sie jedoch alle Elemente aus der Sortierreihenfolge in den Index einbeziehen, selbst wenn Sie übereinstimmende Filter haben.
  • Wenn ich Elasticsearch nach produkt_kategorie:Jackets (Jacken) AND produkt_farbe:Schwarz frage, werden sämtliche Hüte und Schuhe übersprungen, und Elasticsearch kann innerhalb der Jacken nach der Farbe „Black (Schwarz)“ suchen. Sobald diese Einträge gefunden wurden, können alle anderen Farben effizient übersprungen werden.
  • Elasticsearch arbeitet hinter den Kulissen umfassend mit Kompression. Mehrfach vorkommende Werte werden komprimiert, und dies funktioniert am besten, wenn sich die wiederholten Werte im Index nahe zueinander befinden. Wenn sich alle „Jackets (Jacken)“ oder „Farben“ nebeneinander befinden, können diese Werte auf dem Datenträger effizient komprimiert werden. Auf diese Weise wird nicht nur weniger Speicherplatz verbraucht, sondern das Betriebssystem hat auch mehr Platz im Cache des Dateisystems, um andere Vorgänge zu beschleunigen.

Normalerweise macht es Sinn, Sortierreihenfolgen mit aufsteigender Kardinalität zu verwenden, um möglichst viele wiederholte Werte in einer Zeile zu erhalten.

Wie viel Festplattenspeicher werde ich einsparen?

Wie viel Festplattenspeicher können Sie also mit der Indexsortierung einsparen? Wie so oft im Leben ist die Antwort: „Kommt darauf an“. Einer der wichtigsten Faktoren ist die Kardinalität des Felds, nach dem Sie sortieren. Die Platzeinsparungen auf der Festplatte können sich jedoch deutlich bemerkbar machen. Letztes Wochenende habe ich beschlossen, einige IoT-/Heimautomatisierungsdaten aus einem Privatprojekt von einem alten auf einen neuen Computer zu verschieben. Für ein solches Datenmigrationsprojekt gibt es schnellere Wege als Snapshot/Wiederherstellung, aber ich hatte genügend Zeit für eine Reindizierung und wollte sehen, wie viel Platz ich mit der Indexsortierung einsparen kann. Zunächst habe ich die Daten aus der Ferne ohne Sortierung neu indiziert:

status    index           pri    docs.count    docs.deleted    pri.store.size 
open      devices-2017    1      33310674      0               4.2gb

Ich habe knapp über 30 Geräte, die jeweils alle 30 Sekunden einen Status senden. Die Indizierungsrate beträgt also etwa 1 Dokument pro Sekunde. Die Indizierungsgeschwindigkeit kommt nie auch nur in die Nähe der Leistungsgrenze, und ich müsste die Indizierungsrate oder die Anzahl der Geräte dramatisch erhöhen, um dies zu ändern. Diese Anwendung scheint ein guter Kandidat für die Indexsortierung zu sein. Die Daten enthalten Hardware-IDs, Hardwarenamen, Zeitstempel und verschiedene Sensormesswerte wie Temperatur, Aktivitätsstatus eines Geräts zum jeweiligen Zeitpunkt oder andere Sensorwerte. Ich habe den Index nach Geräte-ID und anschließend nach Zeitpunkt sortiert, weil es mir logisch erschien, dass ein bestimmtes Gerät mit relativ hoher Chance ähnliche oder gleiche Werte um einen bestimmten Zeitpunkt herum produziert, was wiederum eine bessere Kompression ermöglicht. Wenn ein Schalter um 7:00:00 in den Zustand „Ein“ versetzt wird, besteht eine recht gute Chance, dass der Schalter um 7:00:30, um 7:01:00 und zumindest für einige weitere Minuten den Zustand „Ein“ hat, die Daten sollten sich daher gut komprimieren lassen. Die Statistiken des sortierten Index zeigen ...

status    index           pri    docs.count     docs.deleted    pri.store.size
open      devices-2017    1      3310674        0               2.5gb

Eine Einsparung von etwa 40 % Platz auf der Festplatte!

Erneute Warnung

An diesem Punkt möchte ich noch einmal ausdrücklich zur Vorsicht mahnen, denn wer würde sich nicht über eine Einsparung von 40 % für dieselben Daten freuen? Ich werde meine Erkenntnisse in zwei kurzen Aussagen zusammenfassen:

  • Ihre Ergebnisse werden abweichen. Ich habe die Indexsortierung an einem anderen Datensatz getestet und eine Einsparung von 20 % gemessen. Überlegen Sie sich gut, nach welchen Feldern Sie sortieren.
  • Ihre Indizierungsrate wird beeinträchtigt. Wenn die Indizierungsgeschwindigkeit wichtig für Sie ist, weil Sie beispielsweise mit einem hohen Loggingvolumen oder mit umfangreichen Metriken arbeiten, dann interessieren Sie sich vermutlich eher für die Anzahl der Dokumente, die Sie in kurzer Zeit indexieren können. In diesem Fall macht es wenig Sinn, die Indexsortierung zu aktivieren.

Wenn Ihnen jedoch der Festplattenspeicher wichtiger ist als die Indizierungsgeschwindigkeit, oder wenn Ihr Indizierungsvolumen niedrig genug und die Geschwindigkeit kein Thema ist, dann können Sie mit der Indexsortierung unter Umständen sehr interessante Ergebnisse erzielen.