Feb 3, 2022
developmentIch hatte vor kurzem eine sehr interessante Fragestellung: RDBMS vs. Graph-Database
Zu diesem Zweck hab ich mir von Oreilly 3 Bücher heruntergeladen und bin diese überflogen, um die Konzepte zu verstehen. Die in den Büchern vorgestellten Datenbanken verwendeten die sogenannte Gremlin Query Language. Trotzdem muss ich sagen: Ich war skeptisch – wie ich bei sehr vielen NoSQL Datenbanken skeptisch bin. Es gibt sicher einige gute (Cassandra, Redis, …) – aber viele scheinen mir auch klassische Sonntagsprojekte zu sein und haben niemals den Tiefgang und die Professionalität von e.g PostgreSQL.
In einem Projekt hatten wir eine sehr einfache Situation: Es gab eine Produkt-Hierarchie. Es gab somit eine Produkttabelle und eine Produkt-2-Produkt Tabelle. In der Doku findet man ein einfaches Beispiel:
Das erste Problem ist, dass man mit CTEs sehr schwer ungerichtete Graphen durchsuchen kann (ich habe lange gesucht und viel probiert – es ging nie performant). Ein ungerichteter Graph muss daher immer durch einen gerichteten abgebildet werden (sie hier).
Des Weiteren stößt man schnell an die Grenzen der Technik, wenn die Tiefe des Baumes groß wird. Folgender Graph liegt in einer Datenbank mit 18 Mio. Kästchen (Produkten) und 54 Mio. Verbindungen zwischen den Kästchen. Pro Graph würde ich im Durchschnitt 30 Kästchen schätzen (es wird vermutlich auf 100 Kästchen steigen). Und mit einer Tiefe – wie im Graph zu sehen ist – ist zu rechnen.
Alleine der rekursive CTE brauchte auf einem sehr performanten Server 1350ms und hatte in der Rekursion 2.999.345 Zeilen. Und das nur, wenn man mit einem der mittleren Knoten anfängt. Fängt man mit dem obesten Knoten an - nach 3 Minuten kein Ergebnis.
Hat man die einzelnen Produkte des Graphs abgefragt (SELECT * FROM product WHERE id IN(….)): 35ms. Und das zeigt auch die Stärken des RDBMS:
Aber: wenn man Abhängigkeiten zwischen Datensätzen darstellen will – schwierig.
Was natürlich auch geht: statt einem CTE einen iterativen PLPGSQL Ansatz. Selbe Datenbank wie oben. 54 Mio. Kanten - Graph aus 50 Knoten - man will alle verbunden Knoten finden.
Funktioniert mit 40msec auch gut. Je nach Graph kann es dann schlechter werden. Da die Stärke eines RDBMS in der Zeilenabfrage ist, würde ich trotzdem Graphen nummerieren (mit anderen Worten: Gibt mir alle Knoten, welche zum Graph X gehören und nicht edge-walking).
Optimiert man das Ganze noch und nutzt die Stärke von SQL: 20msec
Die Grundkonzepte:
Eine Suche könnte wie folgt ausschauen:
Ebenfalls war in einem der Bücher ein Benchmark:
Das schaut schon mal alles sehr interessant aus. Aber ich vermisse sehr viele Dinge von einer RDBMS. Dazu noch zwei Links:
Zuerst dachte ich: RDBMS war eine Fehlentscheidung. Dann rief ich mir die Situation aber nochmal ins Gedächtnis:
D.h.: Irgendwie musste ich die CTE wieder loswerden. Die beste Lösung, die mir eingefallen ist (und die auch am logischsten ist): man führt einfach eine Tabelle „Graph“ ein und jedes Produkt verweist auf diese. Somit kann ich schnell sagen: SELECT * FROM product WHERE graph_id = 99 AND status = Foo.
Ebenfalls könnte ich mir die PolyglotPersistence vorstellen. D.h. einfach die stärken des RDBMS und einer Graph-Datenbanken vereinen.