Ich arbeite an einem Hobbyprojekt namens Menü- / Rezeptverwaltung.
So sehen meine Wesenheiten und ihre Beziehungen aus.
A Nutrient
hat Eigenschaften Code
undValue
An Ingredient
hat eine Sammlung vonNutrients
A Recipe
hat eine Sammlung von Ingredients
und kann gelegentlich eine Sammlung von anderen habenrecipes
A Meal
hat eine Sammlung von Recipes
undIngredients
A Menu
hat eine Sammlung vonMeals
Die Beziehungen können dargestellt werden als
Auf einer der Seiten muss ich für ein ausgewähltes Menü die Informationen zu den wirksamen Nährstoffen anzeigen, die anhand der Bestandteile (Mahlzeiten, Rezepte, Zutaten und die entsprechenden Nährstoffe) berechnet wurden.
Ab sofort verwende ich SQL Server zum Speichern der Daten und navigiere die Kette von meinem C # -Code aus, beginnend mit jeder Mahlzeit des Menüs und aggregiere dann die Nährstoffwerte.
Ich denke, dies ist kein effizienter Weg, da diese Berechnung jedes Mal durchgeführt wird, wenn die Seite angefordert wird und sich die Bestandteile gelegentlich ändern.
Ich habe darüber nachgedacht, einen Hintergrunddienst zu haben, der eine Tabelle mit dem Namen MenuNutrients ( {MenuId, NutrientId, Value}
) verwaltet und diese Tabelle mit den wirksamen Nährstoffen füllt / aktualisiert, wenn sich eine der Komponenten (Mahlzeit, Rezept, Zutat) ändert.
Ich bin der Meinung, dass eine GraphDB gut zu dieser Anforderung passt, aber meine Exposition gegenüber NoSQL ist begrenzt.
Ich möchte wissen, was die alternativen Lösungen / Ansätze für diese Anforderung sind, die Nährstoffe eines bestimmten Menüs anzuzeigen.
Hoffe, meine Beschreibung des Szenarios ist klar.
quelle
Antworten:
Abhängig von den Anforderungen und der Architektur gibt es möglicherweise Optionen zur Leistungsverbesserung:
Sie können indizierte Ansichten (matrialisiert) verwenden, um die Leseleistung auf RDBMS-Ebene (SQL Server) zu verbessern .
Grundsätzlich müssen Sie lediglich:
Eine reguläre Ansicht erstellen.
Erstellen Sie einen Clustered-Index für diese Ansicht .
Die Verwendung eines Einlösemechanismus auf Anwendungsebene verbessert die Leistung.
Wenn es möglich und machbar ist, Cashing zu verwenden, hilft Ihnen eine Cash-Strategie wie Singleton Lazy Cashing .
NoSql:
Es gibt viele gute Artikel über SQL vs NoSql, so und so.
Die Teile interessieren mich:
Wo man NoSql verwendet:
Bei Verwendung bereit sein für:
Neben der Entscheidung , NoSQL, einen hilfreichen Artikel über die Verwendung oder nicht verwenden NoSQL DBMS - Vergleich und die Absicht von ihnen konnte gefunden werden hier als einige von ihnen konzentrieren sich auf die hohe Lesevorgänge, geringe schreibt, karten reduzieren, HA ...
Mit einem Blick bei der Rangfolge und Popularität von ihnen kann nach Kategorie nützlich sein.
quelle
Ich denke, Sie müssen kein Diagramm db verwenden, sondern nur die erforderlichen Werte in einer oberen Ebene speichern. Es ist wie beim Speichern eines
Order
undOrderItems
. Sie müssen nicht jedes Mal die Gesamtsumme berechnen, wenn eine Bestellung angezeigt wird. Stattdessen berechnen Sie einfach Summe, Mehrwertsteuer und andere Dinge und speichern sie bei IhnenOrder
.quelle
Ich schlage vor, das Muster für die Verantwortlichkeit der Befehlsabfrage zu betrachten .
Grundsätzlich können Sie anstelle eines einzelnen Modells zum Lesen und Schreiben zwei verschiedene Modelle erstellen. Eine für die Aktualisierung und die andere für Abfragen (Lesen, Berichten, ...) optimiert. Die beiden Modelle werden mithilfe von Domänenereignissen (normalerweise mit eventueller Konsistenz) synchronisiert (siehe DDD).
Ich habe vor einigen Monaten angefangen, dieses Muster zu studieren, und es hat meine Art, Software zu modellieren, wirklich verändert. Es ist nicht einfach, weil es eine große Veränderung ist, insbesondere wenn es mit anderen Techniken wie DDD und Event Sourcing verwendet wird. Aber es lohnt sich.
Es gibt viele Ressourcen im Internet, die nach CQRS und DDD (und schließlich nach Event Sourcing) suchen.
Dieses Muster kann sowohl in SQL als auch in noSql verwendet werden.
In Ihrem Fall können Sie jedes Mal ein Ereignis auslösen, wenn die Nährstoffe geändert werden, um das Lesemodell zu aktualisieren, das für das Lesen optimiert ist. Das Lesemodell kann beispielsweise eine denormalisierte Ansicht der Nährstoffe des Menüs sein (warum nicht eine nosql-Datenbank für effizientes Lesen verwenden). Sie können mehrere Lesemodelle basierend auf den Abfragen haben, die Sie ausführen müssen.
Dieser Ansatz hat einige Auswirkungen, ist jedoch sehr skalierbar und erweiterbar.
quelle
Es hängt stark davon ab, wie Sie die Menüs und Nährstoffe anfänglich erhalten. Warum wird es Ihrer Meinung nach nicht effizient sein?
Soweit ich weiß, gehen Sie in die DB, holen sich das Menü, gehen dann noch einmal, holen sich jedes Rezept, gehen noch einmal und holen sich jede Zutat und so weiter. Dies ist wirklich ineffizient, da es viele Abfragen und Roundtrips zum Server gibt, was die Hauptursache für Verzögerungen ist. Dies ist als SELECT N + 1-Problem bekannt.
Sie sollten alle Daten in einer einzigen Abfrage abrufen, indem Sie
JOIN
s für alle Tabellen vom Menü bis zu den Nährstoffen verwenden, damit der DB-Server alle Beziehungen und Indizes verwenden kann , um alle Daten gleichzeitig abzurufen . Die Client-C # -App verarbeitet nur das Endergebnis und zeigt es an. Dies ist viel effizienter als eins nach dem anderen.Im Allgemeinen können relationale Datenbanken unter Verwendung geeigneter Abfragetechniken und der richtigen Indizes für kritische Abfragen unter großen Tabellen unter Last sehr gut funktionieren.
quelle
JOIN
Sekunden gibt, die den Server nicht belasten sollten (es sei denn, wir sprechen über das Abrufen von Hunderten oder Tausenden von Zeilen), wenn die Indizierung korrekt ist ist vorhanden. Selbst bei großen Datenmengen können Sie jederzeit eine Ansicht des gesamten Ergebnisses erstellen und die Ansicht sogar indizieren, um das Ergebnis vorab zu berechnen, falls die Leistung jemals zu einem Problem wird.Anscheinend haben Sie einige Zeit damit verbracht, darüber nachzudenken, wie die Daten am besten modelliert werden können, damit sie leicht aktualisiert und abgefragt werden können. Jetzt sind Sie jedoch an dem Punkt angelangt, an dem Sie Zugriff auf die Daten gewähren müssen. Diese beiden Dinge sind getrennte Anliegen.
Sie erwähnen, dass das erneute Laden der Seite eine neue Abfrage in der Datenbank verursacht. Sie erwähnen auch, dass die Datenbank gelegentlich aktualisiert wird und dass diese Aktualisierungen rechtzeitig auf der Seite angezeigt werden sollen. Ihre beste Methode, um den Aufwand für Abfragen zu verringern, besteht darin, sie nicht auszuführen. Wenn Sie immer wieder dieselben Abfragen ausführen und dieselben Ergebnisse erzielen, können Sie sie für eine Weile zwischenspeichern. Sie sollten in der Lage sein, Caching im Upstream zu implementieren, ohne den Rest des Projekts zu ändern. Ich würde empfehlen, über Ruhe zu lesen. Unabhängig davon, ob Sie das Projekt in einem rdbms- oder nosql-Programm implementieren, lassen sich Probleme mit der Leistung dieses Typs am besten beheben, indem Sie die Anzahl der Aufrufe der Datenbank reduzieren. Angenommen, Sie haben in 60 Sekunden 100 Anfragen für dasselbe Rezept. Wenn Sie 60 Sekunden lang zwischenspeichern, haben Sie die Datenbank nur einmal aufgerufen, was eine 100-fache Leistungsverbesserung bedeutet. Um das gleiche Maß an Verbesserung durch den Wechsel zu nosql zu erreichen, ist viel mehr Arbeit erforderlich.
Systeme vom Typ Nosql können eine großartige Lösung sein, wenn Sie große Datenmengen oder extreme Anforderungen an die Lese- oder Schreibgeschwindigkeit haben. Diese zusätzliche Leistung geht jedoch zu Lasten der referenziellen Integrität.
quelle
Es scheint, als ob Sie für das Experiment oder den Wissenszweck Graph-DB ausprobieren möchten, aber Ihr Beispiel ist eindeutig ein Beispiel für hierarchische Daten, bei denen wir einen Drilldown / Up über einen Knoten durchführen können. Ich bin kein Experte für Graph / Neo DB, aber ich kann sehen, dass die Art und Weise, wie Benutzer / Sie Daten aus diesem Schema anfordern können, nicht sehr komplex ist. Ich sehe, dass die Wahl des Datenbank- / Schemadesigns sehr davon abhängt, wie und welche Art von Daten dagegen abgefragt werden. Da Sie SQLSERVER "HierarchyI" verwenden, ist D aus meiner Sicht die beste Option, um diese Knoten als Teil von Tree zu platzieren.
quelle
Mein Vorschlag ist, wie eine Maschine und nicht wie ein Mensch zu denken. Es mag sich wiederholen, aber was Maschinen gut können. Eine Sache, die Sie sich fragen müssen, ist: "Muss ich trotzdem jedes Objekt abrufen, um es auf meiner Seite anzuzeigen?" Wenn ja, fahren Sie fort, was Sie tun. Im Vergleich zum Abrufen von Daten sind CPU-Zyklen bei einfachen Berechnungen vernachlässigbar.
quelle