Quantifizierung von Leistungsgewinnen bei der Batching-Indizierung von Solr-Aktualisierungen
Batching bei der Indizierung ist gut: Seit geraumer Zeit gehört es zum Allgemeinwissen, dass man bei der Indizierung mit SolrJ…
Batching bei der Indizierung ist gut:
Seit geraumer Zeit gehört es zum Allgemeinwissen, dass man bei der Indizierung mit SolrJ (auch mit dem Post-Tool, aber ich schweife ab) Updates in Batches durchführen sollte. Kürzlich hatte ich die Gelegenheit, einen Test zu schreiben, der dieses allgemeine Verständnis mit Zahlen untermauert. Wie üblich, YMMV. Das Interessante daran sind nicht die absoluten Zahlen, sondern die relativen Unterschiede. Ich dachte, es könnte nützlich sein, die Ergebnisse mit Ihnen zu teilen.
Die wichtigsten Erkenntnisse:
Nun, der Titel sagt alles: Batching bei der Indizierung ist gut. Der größte prozentuale Sprung ist die erste Größenordnung, d.h. 10 Dokumente statt 1. Danach steigt zwar der Durchsatz, aber der Sprung von 10 -> 100 ist nicht annähernd so dramatisch wie der Sprung von 1 -> 10. Und das ist bei einer geringen Anzahl von Threads besonders akut.
Ich habe anekdotische Berichte über schrittweise Verbesserungen gehört, wenn Sie zu 10.000 Dokumenten/Paketen übergehen, also rate ich Ihnen, zu experimentieren. Versenden Sie aber nicht jeweils nur ein einziges Dokument und wundern Sie sich dann, warum „die Indizierung in Solr soooooooooo langsam ist“.
Beachten Sie, dass Sie die Ineffizienzen kleiner Stapel ausgleichen können, indem Sie einfach viele Client-Threads auf das Problem ansetzen. Dies verdeutlicht, dass der größte Teil der Zeit im Small-Batch-Szenario für den Aufbau der Verbindung und das Senden der Dokumente über die Leitung aufgewendet wird. Bei bis zu 20 Threads in diesem Experiment steigt der Durchsatz jedoch mit der Größe der Pakete. Und ich habe nicht mehr als 20 Threads ausprobiert.
Alle diese Threads wurden von einem einzigen Programm ausgeführt. Es ist durchaus sinnvoll, stattdessen mehrere Client-Programme laufen zu lassen, wenn die Daten unter ihnen aufgeteilt werden können und/oder Sie sich nicht mit Multi-Threading befassen möchten.
Dies war nicht SolrCloud. Ich würde jedoch erwarten, dass diese allgemeinen Ergebnisse zutreffen, insbesondere wenn CloudSolrClient (CloudSolrServer in 4.x/5x) verwendet wird.
Kleine Schimpftirade:
Schließlich können Sie die CPUs auf den Solr-Servern auslasten. An diesem Punkt haben Sie den maximal möglichen Durchsatz. Ihre Abfrage-Antwortzeit wird natürlich darunter leiden, wenn Sie gleichzeitig indizieren und abfragen. Ich musste diese Bemerkung hier einschieben, weil es ziemlich oft vorkommt, dass Leute auf der Solr-Benutzerliste fragen: „Warum ist meine Indizierung langsam? In mehr als 90 Prozent der Fälle liegt es daran, dass der Client die Dokumente nicht schnell genug an Solr liefert und Solr nur im Leerlauf 10 % der CPU verbraucht. Und es gibt eine sehr Das lässt sich ganz einfach herausfinden… kommentieren Sie die Zeile in Ihrem Programm aus, die Dokumente an Solr sendet, normalerweise eine Zeile wie:
server.add(doclist);
Wie auch immer, genug geschimpft, hier sind die Ergebnisse, über die Umwelt spreche ich dann später:
Schöne tabellarische Ergebnisse:
Wie ich bereits erwähnt habe, habe ich bei 20 Threads aufgehört. Sie könnten den Durchsatz mit mehr Threads erhöhen, aber der allgemeine Trend ist deutlich genug, dass ich aufgehört habe. Die grobe Verdoppelung von 1 auf 2 Threads zeigt, dass Solr die meiste Zeit einfach nur im Leerlauf läuft. Beachten Sie, dass der Anstieg bei 20 Threads nicht mehr linear mit der Anzahl der Threads verläuft und dass das Hinzufügen weiterer Threads den Durchsatz schließlich überhaupt nicht mehr erhöht.
Threads Paketgröße Docs/Sekunde
20 | 1 | 5,714 |
20 | 10 | 16,666 |
20 | 100 | 18,450 |
20 | 1,000 | 20,408 |
2 | 1 | 767 |
2 | 10 | 4,201 |
2 | 100 | 7,751 |
2 | 1,000 | 9,259 |
1 | 1 | 382 |
1 | 10 | 2,369 |
1 | 100 | 5,319 |
1 | 1,000 | 5,464 |
Testumgebung:
- Solr läuft auf einem einzelnen Knoten auf einem Mac Pro mit 64G Arbeitsspeicher, 16G werden Solr zugewiesen. Allerdings ist die Indizierung kein sehr speicherintensiver Vorgang, so dass der Solr zugewiesene Speicher wahrscheinlich kein großes Problem darstellt.
- Die Dateien werden lokal auf einem Macbook Pro Laptop analysiert, der über ein Thunderbolt-Kabel mit dem Mac Pro verbunden ist.
- Die Dokumente sind sehr einfach, es gibt nur ein einziges analysiertes Feld. Der Rest der Felder sind String- oder numerische Felder. Es gibt etwa 30 kurze String-Felder, ein paar Integer-Felder und ein oder zwei Datumsfelder. Hey, das sind die Daten, die ich zur Verfügung hatte!
- Es gibt 200 Dateien mit jeweils 5.000 Dokumenten, also insgesamt 1 Mio. Dokumente.
- Der Index begann immer mit keinen Dokumenten.
- Dies ist das Ergebnis eines einzigen Laufs in jeder Größe.
- Es gibt einen einzigen HttpSolrServer, der von allen Threads des Indizierungsclients gemeinsam genutzt wird.
- Dieser Server wird nicht durch Abfragen belastet.
Wie das Programm funktioniert:
Es gibt zwei Parameter, die bei jedem Durchlauf variieren: die Anzahl der gleichzeitig zu startenden Threads und die Anzahl der Solr-Dokumente, die in jedes an Solr gesendete Paket aufgenommen werden.
Das Programm geht dann rekursiv von einem Stammverzeichnis aus und übergibt jedes Mal, wenn es eine JSON-Datei findet, diese Datei an einen Thread in einem FixedThreadPool, der die Dokumente aus der JSON-Datei parst, sie in Gruppen verpackt und an Solr sendet. Nachdem alle Dateien gefunden wurden, wird gewartet, bis alle Threads fertig sind und der Durchsatz gemeldet.
Ich hatte das Gefühl, dass die Ergebnisse konsistent genug waren, um eine statistisch valide Anzahl von Versuchen durchzuführen, den Durchschnitt aller Versuche zu bilden und, Sie wissen schon, eine ordentliche Analyse zu machen, war nicht sinnvoll.
Fazit:
Stapeln von Dokumenten bei der Verwendung von SolrJ;). Meine Absicht war es, zu begründen, warum Aktualisierungen gebündelt werden sollten. Einfach zu sagen, dass es besser ist, hat viel weniger Aussagekraft als eine 1.400%ige Steigerung des Durchsatzes (1 Thread, der Unterschied zwischen 1 Dokument/Paket und 1.000 Dokumenten/Paket).
Die Gewinne wären weniger dramatisch, wenn Solr mehr Arbeit machen würde, da bin ich mir sicher. Wenn Sie beispielsweise anstelle eines Haufens unanalysierter Felder 6 lange Textfelder mit komplexen Regex-Analyseketten einfügen würden, die Rückverweise verwenden, sähen die Ergebnisse ganz anders aus. Trotzdem ist die Stapelverarbeitung zu empfehlen, wenn dies möglich ist.
Und ich möchte betonen, dass dies auf einem einzelnen, nicht SolrCloud-Knoten geschah, da ich mich ganz auf die Auswirkungen der Stapelverarbeitung konzentrieren wollte. Bei einem ordnungsgemäß eingerichteten SolrCloud-System würde ich erwarten, dass der aggregierte Indizierungsprozess bei Verwendung des CloudSolrClient (CloudSolrServer in 4x) nahezu linear mit der Anzahl der Shards im System skaliert.