Auf Basis von Alfresco Share 3.2.2 haben wir für einen Kunden ein Compliance Management System entwickelt, welches zusätzlich zu Vertrags- bzw. Dokumentvorlagen, organisatorischen Strukturen und komplexen Workflows zur Einhaltung der Prüfungs-, Freigabe- und Dokumentationsprozesse auch die Verwaltung von ca. 500.000+ Stammdatensätze umfasst. Letztere sind als abstrakter Inhaltstyp mit Aspekten zur Gruppierung von Datenfeldern modelliert und werden regelmäßig durch einen Import mit einem externen System abgeglichen. Die Datensätze liegen allesamt im regulären ContentStore “workspace://SpacesStore”, denn 500.000 Objekte mit ca. 20 Metadatenfeldern sind nicht aureichend, um eine nennenswerte Auswirkung auf die Performance des Gesamtsystems erwarten zu können.
Entgegen den Erwartungen wurde ein Problem auf Basis von Alfresco-Eigenheiten bei der Sortierung von Lucene-Suchen beobachtet. Da der Inhaltstyp cm:cmobject als Vatertyp nutzt, hat jedes Objekt auch die geerbte Eigenschaft cm:name, welche wir mit dem Wert des fachlich eindeutigen Datensatzschlüssels belegen. Nach der ersten Synchronisierung enthielt der Index 500.000+ zusätzliche, 100% distinkte Werte für das Feld @cm:name, was zu einem merklichen Einbruch der Performance der Share Documentlibrary Navigation führte. Für uns ergab sich für jede auf @cm:name sortierende Suche ein Grund-Overhead von 3 – 5 s, bevor überhaupt die eigentliche Suche lief. Da jede Navigation innerhalb der Share Documentlibrary eine sortierende Suche in doclist.get.js auslöst, ist die Gesamtanwendung daher untragbar beeinflusst.
Warum verhält sich Alfresco schon bei einer (scheinbar) kleinen Datenmenge so schlecht? Hierfür gibt es technisch gesehen 2 Hauptgründe:
- Alle Feldwerte werden bei einer sortierenden Suche aus dem Index in den Speicher geladen, um vorsortiert zu werden (bei uns ca. 800.000+ distinkte Werte bei üblicherweise < 50 zu sortierenden Ergebnissen auf einer Seite).
- Der Lucene interne FieldCache kann bei wiederholten Anfragen nicht optimierend wirken. Bei jeder Suche kommt aufgrund der mehrfachen Kapselung des eigentlichen IndexReader eine unterschiedliche “Kapsel”-Instanz zur Geltung – der FieldCache kann per Kontrakt nur für die exakt gleiche Instanz schon geladene Werte zurückgegeben. Es werden also immer alle Feldwerte brav neu geladen. (Wer Zeit und Muße hat, kann sich den Cache mal mit einem Java Debugger anschauen und wird feststellen, dass die benötigten Daten i.d.R. schon mehrfach vorliegen aber nicht abgegriffen werden können.)
Je nachdem wie performant die I/O des Datenträgers ist, auf welchem der Index abgelegt wird, ergibt sich ein mehr oder weniger starker Effekt. Mit meinem persönlichen Arbeitslaptop inklusive SSD hab ich für gewöhnlich mehr Leistung als der Kunde für seine produktiven Maschinen zu zahlen bereit ist, und bleibe mit 1 – 2 s Verzögerung relativ verschont – bei intensiver Navigation fällt Anwendern aber auch das schnell negativ auf.
Welche Lösungen / Ansätze gibt es für die Performanceprobleme bei sortierenden Suchen?
- Große Mengen an Stammdatensätzen sollten in andere ContentStores ausgelagert werden (separater Index). Dies geht jedoch nur, wenn keine oder nur einfach abbildbare Hierarchien mit sonstigen Inhaltsstrukturen bestehen (sollen).
- Wenn möglich sollten Merkmale zur Sortierung über eigene, fachliche Metadaten abgebildet werden. Sobald standardisierte Eigenschaften verwendet werden, ist die Gefahr groß, durch größere Datensätze Seiteneffekte bzgl. der Sortierperformance anderer Datenbestände zu verursachen.
- Bei Suchen über kleinere Teilmengen kann im Extremfall die Sortierung (inkl. Paging) auf JavaScript- oder Java-Seite schneller sein als mittels Lucene. (Dies wäre z.B. bei uns im Fall der Documentlibrary Navigation so, da i.d.R. nur 5 – 15 Elemente in einer Ebene liegen.)
- Migration auf Alfresco 4.0 mit SOLR / Canned Queries
Für mich war das eine eher überraschende Erkenntnis, bedeutet es doch, dass in Alfresco bzw. Share nur wenige 100.000e Dokumente verwaltet werden können, bevor die Kernkomponente Documentlibrary langsamer reagiert. Das passte nun gar nicht zu meiner bisherigen Erfahrung, die u.a. die Verwaltung von mehreren Millionen von Objekten in einer einzigen Alfresco Instanz umfasst …
Die Probleme die Sortierung betreffend sind Alfresco schon längere Zeit bekannt. Zusammen mit ähnlichen Problemen bei PATH-basierten Suchen und Berechtigungsprüfungen bei großen Ergebnismengen wurde diese als Anlass / Bestärkung genommen, mit Alfresco 4.0 den Wechsel auf SOLR zu vollziehen sowie zentrale Abfragen auf die Datenbank zu verlegen. Gerade die Canned Queries garantieren bei Alfresco 4.0, dass bei einer sortierenden Abfrage nur die Eigenschaften der tatsächlich in der abgefragten Ebene befindlichen Objekte berücksichtigt werden.
0 Kommentare.