Apache Solr Segmentzusammenführung, gelöschte Dokumente und warum Optimize schlecht für Sie sein kann

So optimieren Sie Ihren Apache Solr-Index, indem Sie Segmente zusammenführen, um Platzverschwendung durch gelöschte Dokumente zu vermeiden. Für Apache Solr 7.4 und früher.

Dieser Artikel bezieht sich auf Apache Solr 7.4 und früher. Das in diesem Beitrag beschriebene Verhalten ist nicht das Standardverhalten in späteren Versionen von Solr. Für Solr 7.5 und spätere Versionen gehen Sie zu Solr und Optimieren Ihres Index: Teil II. Dieser Artikel ist dennoch relevantes Hintergrundmaterial, um zu verstehen, warum das neuere Standardverhalten vorzuziehen ist.

Solr Merge-Richtlinie und gelöschte Dokumente

Wenn ein Dokument während der Indizierung gelöscht oder aktualisiert wird, wird es nicht wirklich sofort aus dem Index entfernt. Das Dokument wird lediglich in seinem ursprünglichen Segment als „gelöscht“ markiert. Es wird nicht in den Suchergebnissen angezeigt (oder die neue Version wird im Falle einer Aktualisierung gefunden). Dies führt zu einem gewissen Prozentsatz an „Verschwendung“. Ihr Index kann z.B. aus 15%-20% gelöschten Dokumenten bestehen.

In manchen Situationen liegt die Menge des verschwendeten Speicherplatzes näher bei 50%. Und es gibt Situationen, in denen der Prozentsatz der gelöschten Dokumente sogar noch höher sein kann. Dies wird durch das Verhältnis von numDocs zu maxDocs in der Admin-Oberfläche von Solr bestimmt.

Wenn die Hälfte oder mehr Ihres Indexes „verschwendet“ ist, ist das nicht ideal. Dieser Artikel erklärt, wie es dazu kommt und was Sie dagegen tun können. Spoiler: nicht viel.

HINWEIS: Wir sprechen von „gelöschten“ Dokumenten. Für die Zwecke dieses Artikels umfasst der Begriff „gelöscht“ sowohl explizite Löschungen als auch Aktualisierungen bestehender Dokumente. Letzteres wird durch ein Löschen des Originaldokuments gefolgt von einem Hinzufügen realisiert.

Gute Nachrichten, schlechte Nachrichten

Die gute Nachricht ist, dass es leicht zu vermeiden ist, dass mehr als 50 % Ihres Index aus gelöschten Dokumenten bestehen; optimieren Sie nicht. Wir werden später darüber sprechen, wie die Optimierung (auch bekannt als forceMerge) dazu führen kann, dass mehr als 50% des Index aus gelöschten Dokumenten bestehen.

Die schlechte Nachricht ist, dass es ab Solr 7.0.1 keine Konfigurationseinstellung gibt, die garantiert, dass nicht mehr als 50% Ihres Index aus gelöschten Dokumenten bestehen. Sie können diese Diskussion und die Lösung auf der Apache JIRA Liste unter LUCENE-7976 nachlesen .

Apache Lucene Segmente sind „einmalig schreibbar“.

Lucene-Indizes sind seit jeher aus „Segmenten“ aufgebaut. Ein einzelnes Segment besteht aus mehreren Dateien, die denselben Stammnamen, aber unterschiedliche Erweiterungen haben. Ein einzelnes Segment besteht aus Dateien wie _0.fdt, _0.fdx, _0.tim und dergleichen.

Lucene verfolgt in Bezug auf Segmente eine „write once“-Politik. Immer wenn ein „Hard Commit“ erfolgt, wird das aktuelle Segment geschlossen und ein neues geöffnet. In dieses Segment wird nie wieder geschrieben [1]. Nehmen wir also an, ein Segment enthält 10.000 Dokumente. Sobald das Segment geschlossen ist, wird es immer 10.000 Dokumente enthalten, auch wenn einige davon als gelöscht markiert sind.

Das kann nicht ewig so weitergehen. Sie würden sonst keine Datei-Handles mehr haben.

Zusammenführung zur Rettung

Die Lösung ist „Zusammenführen“. Wir haben bereits erwähnt, dass bei einer Übertragung das Segment geschlossen wird. Zu diesem Zeitpunkt prüft Lucene den Index auf Segmente, die zusammengeführt werden können. Es gibt mehrere „Zusammenführungsrichtlinien“, die alle entscheiden, dass einige Segmente zu einem neuen Segment kombiniert werden können und die alten Segmente, die zusammengeführt wurden, entfernt werden können. Der kritische Punkt ist, dass bei der Zusammenführung von Segmenten das Ergebnis nicht die gelöschten Dokumente enthält.

Nehmen wir an, es gibt zwei Segmente, die jeweils aus 10.000 Dokumenten bestehen, von denen 2.500 gelöscht sind. Diese beiden Segmente werden zu einem einzigen neuen Segment zusammengefasst, das aus 15.000 Dokumenten besteht. Die 2.500 gelöschten Dokumente aus jedem ursprünglichen Segment werden bei der Zusammenführung bereinigt.

Jedenfalls so weit, so gut. Und die standardmäßige TieredMergePolicy (TMP) hält die Anzahl der gelöschten Dokumente in einem Index normalerweise bei etwa 10-15%.

Es stellt sich jedoch heraus, dass es Situationen gibt, in denen die verschiedenen Zusammenführungsrichtlinien zu Verhaltensweisen führen, die bis zu 50% gelöschte Dokumente in einem Index zur Folge haben können.

Warum erfolgt die Zusammenführung auf diese Weise?

Es ist immer eine Gratwanderung, wenn Sie Zusammenführungsrichtlinien erstellen. Einige Optionen sind:

  • Führen Sie alle Segmente mit gelöschten Dokumenten zusammen. Die E/A würde durch die Decke gehen und die Leistung der Indizierung (und der Abfrage beim Zusammenführen) würde drastisch sinken. Im schlimmsten Fall würden Sie Ihren gesamten Index neu schreiben, nachdem Sie 0,01% Ihrer Dokumente gelöscht haben.
  • Die Daten aus den Segmenten wiederherstellen, wenn Dokumente gelöscht wurden. Leider würde das bedeuten, dass der gesamte Index neu geschrieben werden müsste. Es handelt sich um sehr komplexe Strukturen, und ein einfaches Löschen der mit einem Dokument verknüpften Informationen ist unverhältnismäßig teuer.

In diesem Diagramm zeigen die schattierten Bereiche gelöschte Dokumente an. a, b, d, e, g und h haben etwa 60% gelöschte Dokumente, c und f 20%.

Was? Ich kann mir 50% „verschwendeten“ Platz nicht leisten!

In der Tat. Doch wie kommt es überhaupt dazu? Nun, das ist ein wenig kompliziert. Beachten Sie, dass es eine „maximale Segmentgröße“ gibt, die standardmäßig auf 5G eingestellt ist, die ich hier verwende und die höher oder niedriger konfiguriert werden kann.

Das Grundproblem ist, dass nur Segmente mit < 50% „max segment size“ Live-Dokumenten für die Zusammenführung in Frage kommen.

Nehmen wir einen idealisierten 200G-Index, der aus genau 40 Segmenten mit einer Größe von jeweils 5G besteht. Nehmen wir weiter an, dass die Dokumente im Korpus zufällig aktualisiert werden. Keines dieser Segmente kommt für eine Zusammenführung in Frage, bis sie < 2,5G „lebende“ Dokumente enthalten. Letztendlich werden alle ursprünglichen 40 Segmente 2,51G „lebende“ Dokumente enthalten (oder für mich nahe genug an 50%).

Den Bericht von Michael McCandless können Sie hier einsehen , mit Grafiken! Er war maßgeblich an der Zusammenführung des Codes beteiligt.

Was kann ich dagegen tun?

Leider nicht viel. Hier sind einige Ideen, die andere hatten:

  • forceMerge (auch bekannt als optimize) oder expungeDeletes. Diese Operationen entfernen in der Tat alle gelöschten Dokumente, wenn Sie forceMerge und alle Segmente über einem bestimmten Prozentsatz in expungeDeletes zusammenführen. Der Nachteil dabei ist jedoch, dass Sie, wenn Sie einmal optimiert haben, dies auch weiterhin tun müssen oder mit vielen gelöschten Dokumenten leben müssen [2]. Der Grund dafür ist, dass forceMerge (und expungeDeletes im Übrigen) ein großes Segment als Ergebnis erzeugt [3]. In einem 100G-Index wird dieses einzelne Segment 100G groß sein, obwohl die maximale Segmentgröße (standardmäßig) 5G beträgt. Um nun für die Zusammenführung in Frage zu kommen, muss dieses einzelne große Segment < 2,5G „lebende“ Dokumente enthalten, d.h. es hat bis zu 97,5% ungenutzten Speicherplatz.
  • Vergrößern Sie die maximale Segmentgröße. Wir haben bereits erwähnt, dass dies standardmäßig auf 5G eingestellt ist, was durch eine Einstellung in solrconfig.xml geändert werden kann. Die Änderung der maximalen Segmentgröße macht keinen Unterschied, da das Problem nicht darin besteht, wie groß jedes Segment sein kann, sondern darin, dass das Segment erst dann für die Zusammenführung in Betracht gezogen wird, wenn < 50% der maximalen Segmentgröße ungelöschte Dokumente enthält.
  • Tauchen Sie in die Geheimnisse der Zusammenführungsrichtlinie ein und ändern Sie einige der untergeordneten Parameter. Es gibt Eigenschaften wie „reclaimDeletesWeight“, die Sie über TieredMergePolicy in solrconfig.xml konfigurieren können. Keiner dieser Parameter ist von Bedeutung, da sie erst dann zum Tragen kommen, wenn das Segment < 50% (maximale Segmentgröße) lebende Dokumente enthält, und es gibt keine Möglichkeit, dies zu konfigurieren.

So Where Exactly Does That Leave Us?

Die Lucene-Indizierung hat uns seit Jahren gute Dienste geleistet, daher ist dies ein Sonderfall. Wenn Sie keine Ressourcenprobleme haben, lassen Sie das Zusammenführen am besten sein. Wenn Sie dieses Problem lösen müssen, gibt es derzeit nur wenige Möglichkeiten:

  • Optimieren/Zusammenführen/ExpungeLöschen. Mit diesen Optionen können Sie einige oder alle gelöschten Dokumente aus Ihrem Index entfernen. Wie oben beschrieben, erzeugen diese Operationen jedoch Segmente, die viel größer sind als das Maximum, das für zukünftige Zusammenführungen in Frage kommt, und Sie müssen diese Operationen routinemäßig durchführen. DIE OPTIMIERUNG WIRD FÜR NRT-INDIZES NICHT EMPFOHLEN! Dies sind sehr schwergewichtige Operationen, die im Allgemeinen nur für sehr langsam wechselnde Indizes geeignet sind. Wenn Sie nur in regelmäßigen Abständen indexieren (z.B. einmal am Tag) und sich die Zeit leisten können, den Index jedes Mal zu optimieren, wenn Sie ihn neu erstellen, dann ist eine Optimierung durchaus sinnvoll.
  • Führen Sie optimize/forceMerge auf geschickte Weise aus. Optional können Sie die Operation optimize/forceMerge anweisen, in N Segmenten statt nur in einem einzigen zusammenzuführen, wobei N etwa (Fudge-Faktor) + (Gesamtgröße des Index)/(maximale Segmentgröße) ist. Theoretisch würde dies nicht zu der pathologischen Situation führen, dass > 50% Ihres Indexes aus gelöschten Dokumenten besteht. Dieses Verhalten wird nicht explizit unterstützt, so dass ich mit einer Vorhersage sehr zurückhaltend wäre.
  • Ändern Sie den Code. Erstellen Sie entweder einen Patch für LUCENE-7976 oder schlagen Sie eine neue Zusammenführungsrichtlinie vor.

Fazit

Dieser Artikel sieht beängstigend aus, aber denken Sie daran, dass es die TieredMergePolicy schon lange gibt und sie sich bewährt hat. Wir haben dieses Dokument erstellt, um eine Referenz für die Situationen zu bieten, in denen Benutzer feststellen, dass ihr Index aus einem größeren Anteil gelöschter Dokumente besteht als erwartet. Da Solr und Lucene sich auf immer größere Dokumentensätze zubewegen, könnte es an der Zeit sein, TieredMergePolicy zu optimieren und/oder eine neue Merge-Policy zu erstellen, und diese Diskussion ist bereits im Gange.


[1] Wir vereinfachen hier ein wenig. Die Dokumente in diesem Segment werden in einer separaten Datei, die mit dem Segment verknüpft ist, als gelöscht markiert, d.h. das Segment wird in diesem Sinne beschrieben, nachdem es geschlossen wurde. Aber das ist für diese Diskussion unerheblich.

[2] Wir vereinfachen hier wieder. Wenn sich Ihr Index nicht ändert oder wenn Sie immer neue Dokumente hinzufügen, so dass keine Dokumente jemals aktualisiert oder gelöscht werden, hat die Optimierung diesen Nachteil nicht, da es keine gelöschten Dokumente in Ihrem Index gibt und die Antwortzeit verbessert wird.

[3] Sie können angeben, dass das Ergebnis von forceMerge mehr als ein Segment sein soll, aber das ändert nichts an der Gesamtsituation.


Dieser Beitrag wurde ursprünglich am 13. Oktober 2017 veröffentlicht.

You Might Also Like

Vom Suchunternehmen zum praktischen KI-Pionier: Unsere Vision für 2025 und darüber hinaus

CEO Mike Sinoway gibt Einblicke in die Zukunft der KI und stellt...

Read More

Wenn KI schief geht: Fehlschläge in der realen Welt und wie man sie vermeidet

Lassen Sie nicht zu, dass Ihr KI-Chatbot einen 50.000 Dollar teuren Tahoe...

Read More

Lucidworks Kernpakete: Branchenoptimierte KI-Such- und Personalisierungslösungen

Entdecken Sie unsere umfassenden Core Packages, die Analytics Studio, Commerce Studio und...

Read More

Quick Links