Wir haben ein Programm, das ständig läuft, verschiedene Dinge tut und einige Datensätze in unserer Datenbank ändert. Diese Datensätze werden mit Lucene indiziert. Jedes Mal, wenn wir eine Entität ändern, machen wir so etwas wie:
indexWriter.deleteDocuments(..)
und dann indexWriter.addDocument(..)
. Das funktioniert gut, aber im Laufe der Zeit benötigt indexWriter.commit()
immer mehr Zeit. Anfangs dauert es ungefähr 0,5 Sekunden, aber nach ein paar hundert solcher Transaktionen dauert es mehr als 3 Sekunden. Ich bezweifle nicht, dass es noch länger dauern würde, wenn das Skript länger laufen würde.
Meine bisherige Lösung bestand darin, die indexWriter.addDocument(..)
und indexWriter.commit()
auskommentieren und den gesamten Index hin und wieder neu erstellen, indem Sie zuerst indexWriter.deleteAll()
verwenden und dann alle Dokumente innerhalb einer Lucene-Transaktion / IndexWriter ( ungefähr 250k Dokumente in ungefähr 14 Sekunden). Dies widerspricht jedoch offensichtlich dem transaktionalen Ansatz von Datenbanken und Lucene, der beide synchron hält und die Aktualisierungen für die Benutzer unserer Tools, die mit Lucene suchen, für die Datenbank sichtbar macht.
Es ist merkwürdig, dass ich in 14 Sekunden 250.000 Dokumente hinzufügen kann, aber das Hinzufügen von 1 Dokument dauert 3 Sekunden. Was mache ich falsch, wie kann ich die Situation verbessern?
Was Sie falsch machen, ist die Annahme, dass die integrierten Transaktionsfunktionen von Lucene Leistung haben und Garantien, die mit einer typischen relationalen Datenbank vergleichbar sind, wenn sie wirklich nicht . Genauer gesagt synchronisiert ein Commit in diesem Fall alle Indexdateien mit dem Datenträger, wodurch die Commit-Zeiten proportional zur Indexgröße sind. Deshalb benötigt Ihr indexWriter.commit()
im Laufe der Zeit immer mehr Zeit. Die Javadoc für IndexWriter.commit()
warnt sogar das:
Dies kann eine kostspielige Operation sein, also sollten Sie die Kosten in Ihrem testen Anwendung und tun Sie es nur, wenn wirklich notwendig.
Können Sie sich eine Datenbank-Dokumentation vorstellen, die Sie auffordert, Commits zu vermeiden?
Da Ihr Hauptziel darin besteht, Datenbankupdates durch Lucene-Suchen zeitnah sichtbar zu halten, tun Sie Folgendes, um die Situation zu verbessern:
indexWriter.deleteDocuments(..)
und indexWriter.addDocument(..)
nach einem erfolgreichen Datenbank-Commit anstelle von indexWriter.commit()
in regelmäßigen Abständen statt jeder Transaktion aus, nur um sicherzustellen, dass Ihre Änderungen letztendlich auf den Datenträger geschrieben werden SearcherManager
zum Suchen und Aufrufen maybeRefresh()
regelmäßig, um aktualisierte Dokumente anzuzeigen innerhalb eines angemessenen Zeitrahmens Im folgenden Beispielprogramm wird gezeigt, wie Dokumentupdates abgerufen werden können, indem Sie maybeRefresh()
regelmäßig ausführen. Es erstellt einen Index von 100000 Dokumenten, verwendet eine ScheduledExecutorService
Um periodische Aufrufe von commit()
und maybeRefresh()
einzurichten, werden Sie aufgefordert, ein einzelnes Dokument zu aktualisieren. Anschließend wird wiederholt gesucht, bis das Update sichtbar ist. Alle Ressourcen werden beim Beenden des Programms ordnungsgemäß bereinigt. Beachten Sie, dass der steuernde Faktor für den Zeitpunkt, zu dem die Aktualisierung sichtbar wird, ist, wenn maybeRefresh()
aufgerufen wird, nicht commit()
.
Dieses Beispiel wurde erfolgreich mit Lucene 5.3.1 und JDK 1.8.0_66 getestet.
Mein erster Ansatz: Begib dich nicht so oft. Wenn Sie ein Dokument löschen und erneut hinzufügen, wird wahrscheinlich eine Zusammenführung ausgelöst. Zusammenführungen sind etwas langsam.
Wenn Sie einen Fast-Real-Time-IndexReader verwenden, können Sie immer noch wie gewohnt suchen (es werden keine gelöschten Dokumente angezeigt), aber Sie erhalten keine Commit-Strafe. Sie können das Commit später durchführen, um sicherzustellen, dass das Dateisystem mit Ihrem Index übereinstimmt. Sie können dies während der Verwendung Ihres Indexes tun, damit Sie nicht alle anderen Operationen blockieren müssen.
Siehe auch diesen interessanten Blogeintrag (und tun Sie es Lesen Sie auch die anderen Beiträge, sie bieten großartige Informationen).
Tags und Links java performance indexing lucene