Angenommen, ich erstelle ein Blog, in dem ich Beiträge und Kommentare veröffentlichen möchte. Also erstelle ich zwei Tabellen, eine 'posts'-Tabelle mit einer automatisch inkrementierenden Integer-ID-Spalte und eine' comments'-Tabelle mit dem Fremdschlüssel 'post_id'.
Dann möchte ich ausführen, was wahrscheinlich meine häufigste Abfrage ist, nämlich das Abrufen eines Posts und aller seiner Kommentare. Da relationale Datenbanken noch relativ neu sind, erscheint es mir am offensichtlichsten, eine Abfrage zu schreiben, die ungefähr so aussieht:
SELECT id, content, (SELECT * FROM comments WHERE post_id = 7) AS comments
FROM posts
WHERE id = 7
Das würde mir die ID und den Inhalt des Posts geben, den ich möchte, zusammen mit allen relevanten Kommentarzeilen, die ordentlich in ein Array gepackt sind (eine verschachtelte Darstellung, wie Sie sie in JSON verwenden würden). Natürlich funktionieren SQL-Datenbanken und relationale Datenbanken nicht so, und das Beste, was sie erreichen können, ist eine Verknüpfung zwischen "Posts" und "Kommentaren", die eine Menge unnötiger Duplikate von Daten zurückgibt (wobei dieselben Post-Informationen wiederholt werden in jeder Zeile), was bedeutet, dass die Verarbeitungszeit sowohl für die Datenbank aufgewendet wird, um alles zusammenzusetzen, als auch für meinen ORM, um alles zu analysieren und rückgängig zu machen.
Selbst wenn ich meinen ORM anweise, die Kommentare des Posts eifrig zu laden, ist es am besten, eine Abfrage für den Post und dann eine zweite Abfrage zum Abrufen aller Kommentare zu senden und sie dann clientseitig zusammenzustellen ist auch ineffizient.
Ich verstehe, dass relationale Datenbanken bewährte Technologie sind (zum Teufel, sie sind älter als ich), und dass im Laufe der Jahrzehnte eine Menge Forschung in sie gesteckt wurde, und ich bin mir sicher, dass es einen wirklich guten Grund gibt, warum sie (und die) SQL-Standard) funktionieren so, wie sie es tun, aber ich bin mir nicht sicher, warum der oben beschriebene Ansatz nicht möglich ist. Es scheint mir die einfachste und naheliegendste Möglichkeit zu sein, eine der grundlegendsten Beziehungen zwischen Datensätzen zu implementieren. Warum bieten relationale Datenbanken so etwas nicht an?
(Haftungsausschluss: Ich schreibe hauptsächlich Webapps mit Rails und NoSQL-Datenspeichern, aber kürzlich habe ich Postgres ausprobiert und es gefällt mir sehr gut. Ich will keine relationalen Datenbanken angreifen, ich bin nur ratlos.)
Ich frage nicht, wie ich eine Rails-App optimieren oder mich in einer bestimmten Datenbank um dieses Problem kümmern soll. Ich frage mich, warum der SQL-Standard so funktioniert, wenn er mir nicht intuitiv und verschwenderisch erscheint. Es muss einen historischen Grund geben, warum die ursprünglichen Designer von SQL wollten, dass ihre Ergebnisse so aussehen.
Antworten:
CJ Date geht ausführlich auf dieses Thema in Kapitel 7 und Anhang B der SQL- und relationalen Theorie ein . Sie haben Recht, nichts in der relationalen Theorie verbietet, dass der Datentyp eines Attributs selbst eine Relation ist, solange er in jeder Zeile der gleiche Relationstyp ist. Ihr Beispiel würde sich qualifizieren.
Laut Date sind solche Strukturen "normalerweise - aber nicht immer - kontraindiziert" (dh eine schlechte Idee), da die Hierarchien der Beziehungen asymmetrisch sind . Beispielsweise kann eine Umwandlung von einer verschachtelten Struktur in eine vertraute "flache" Struktur nicht immer rückgängig gemacht werden, um die Verschachtelung wiederherzustellen.
Abfragen, Einschränkungen und Aktualisierungen sind komplexer, schwieriger zu schreiben und für das RDBMS schwieriger zu unterstützen, wenn Sie Attribute mit Bezugswerten (RVA) zulassen.
Außerdem werden die Prinzipien des Datenbankdesigns durcheinandergebracht, da die beste Hierarchie der Beziehungen nicht so klar ist. Sollten wir eine Beziehung von Lieferanten mit einer verschachtelten RVA für Teile entwerfen, die von einem bestimmten Lieferanten geliefert werden? Oder eine Beziehung von Teilen mit einer verschachtelten RVA für Lieferanten, die ein bestimmtes Teil liefern? Oder beide speichern, um die Ausführung verschiedener Abfragetypen zu vereinfachen?
Dies ist das gleiche Dilemma, das sich aus der hierarchischen Datenbank und den dokumentenorientierten Datenbankmodellen ergibt . Aufgrund der Komplexität und der Kosten für den Zugriff auf verschachtelte Datenstrukturen müssen Designer die Daten redundant speichern, um sie bei verschiedenen Abfragen leichter nachschlagen zu können. Das relationale Modell rät von Redundanz ab, sodass RVAs gegen die Ziele der relationalen Modellierung arbeiten können.
Soweit ich weiß (ich habe sie nicht verwendet), sind Rel und Dataphor RDBMS-Projekte, die Attribute mit Bezugswerten unterstützen.
Kommentar von @dportas:
Strukturierte Typen sind Teil von SQL-99, und Oracle unterstützt diese. Sie speichern jedoch nicht mehrere Tupel in der verschachtelten Tabelle pro Zeile der Basistabelle. Das übliche Beispiel ist ein "Adresse" -Attribut, das eine einzelne Spalte der Basistabelle zu sein scheint, aber weitere Unterspalten für Straße, Stadt, Postleitzahl usw. enthält.
Geschachtelte Tabellen werden auch von Oracle unterstützt und ermöglichen mehrere Tupel pro Zeile der Basistabelle. Mir ist jedoch nicht bewusst, dass dies Teil von Standard-SQL ist. Und denken Sie an die Schlussfolgerung eines Blogs: "Ich werde niemals eine verschachtelte Tabelle in einer CREATE TABLE-Anweisung verwenden. Sie verbringen die ganze Zeit damit, sie UN-NESTING zu machen, um sie wieder nützlich zu machen!"
quelle
x
den Wert von Ganzzahl 42 haben kann). Dieselben Operationen gelten für Relationen und Relvare, daher muss ihre Struktur kompatibel sein.Einige der frühesten Datenbanksysteme basierten auf dem Modell der hierarchischen Datenbank . Dies stellte Daten in einer baumartigen Struktur mit übergeordneten und untergeordneten Elementen dar, wie Sie es hier vorschlagen. HDMS wurden weitgehend von Datenbanken abgelöst, die auf dem relationalen Modell aufbauten. Die Hauptgründe dafür waren, dass RDBMS "viele zu viele" Beziehungen modellieren konnte, die für hierarchische Datenbanken schwierig waren, und dass RDBMS problemlos Abfragen durchführen konnte, die nicht Teil des ursprünglichen Entwurfs waren, während HDBMS Sie dazu zwang, Pfade abzufragen, die zur Entwurfszeit angegeben wurden.
Es gibt immer noch einige Beispiele für hierarchische Datenbanksysteme in freier Wildbahn, insbesondere die Windows-Registrierung und LDAP.
Ausführliche Informationen zu diesem Thema finden Sie im folgenden Artikel
quelle
Ich nehme an, dass sich Ihre Frage wirklich auf die Tatsache konzentriert, dass Datenbanken zwar auf einer soliden Logik und einer soliden theoretischen Grundlage basieren und sehr gute Arbeit beim Speichern, Bearbeiten und Abrufen von Daten in (zweidimensionalen) Sätzen leisten, während gleichzeitig die referenzielle Integrität und die Parallelität gewährleistet sind und viele andere Dinge, bieten sie keine (zusätzliche) Funktion zum Senden (und Empfangen) von Daten in einem, wie man es nennen könnte, objektorientierten Format oder hierarchischen Format.
Dann behaupten Sie, dass "selbst wenn ich meinen ORM anweise, die Kommentare des Posts eifrig zu laden, das Beste ist, eine Abfrage für den Post zu senden und dann eine zweite Abfrage, um alle Kommentare abzurufen und sie dann zusammenzufügen Client-Seite, die auch ineffizient ist " .
Ich sehe nichts Ineffizientes beim Senden von 2 Abfragen und Empfangen von 2 Ergebnissätzen mit:
Ich würde argumentieren, dass dies (fast) der effizienteste Weg ist (fast, da Sie die
posts.id
und nicht alle Spalten von nicht wirklich benötigencomments.*
).Wie Todd in seinem Kommentar ausführte, sollten Sie die Datenbank nicht auffordern, Daten zur Anzeige zurückzugeben. Es ist die Aufgabe der Anwendung, dies zu tun. Sie können (eine oder mehrere) Abfragen schreiben, um die Ergebnisse zu erhalten, die Sie für jeden Anzeigevorgang benötigen, damit die Daten, die über die Leitung (oder den Speicherbus) von der Datenbank zur Anwendung gesendet werden, nicht unnötig dupliziert werden.
Ich kann nicht wirklich über ORMs sprechen, aber vielleicht können einige von ihnen einen Teil dieser Arbeit für uns erledigen.
Ähnliche Techniken können bei der Übermittlung von Daten zwischen einem Webserver und einem Client verwendet werden. Andere Techniken (wie das Zwischenspeichern) werden verwendet, damit die Datenbank (oder das Web oder ein anderer Server) nicht mit doppelten Anforderungen überlastet wird.
Ich vermute, dass Standards wie SQL am besten sind, wenn sie auf einen Bereich spezialisiert bleiben und nicht versuchen, alle Bereiche eines Bereichs abzudecken.
Andererseits könnte das Komitee, das den SQL-Standard festlegt, in Zukunft auch anders denken und eine Standardisierung für eine solche zusätzliche Funktion bereitstellen. Aber es ist nicht etwas, das in einer Nacht entworfen werden kann.
quelle
Ich bin nicht in der Lage, mit einer richtigen, argumentierten Antwort zu antworten. Wenn ich falsch liege, können Sie mich in Vergessenheit geraten lassen (aber bitte korrigieren Sie mich, damit wir etwas Neues lernen können). Ich denke, der Grund dafür ist, dass relationale Datenbanken sich auf das relationale Modell konzentrieren, das wiederum auf etwas basiert, von dem ich nichts weiß, und das als "Logik erster Ordnung" bezeichnet wird. Was Sie vielleicht fragen, passt konzeptionell wahrscheinlich nicht in den mathematisch / logischen Rahmen, auf dem relationale Datenbanken aufbauen. Darüber hinaus lässt sich das, wonach Sie fragen, in der Regel leicht durch Diagrammdatenbanken lösen. Dies weist darauf hin, dass die zugrunde liegende Konzeptualisierung der Datenbank im Widerspruch zu dem steht, was Sie erreichen möchten.
quelle
Ich weiß, dass SQL Server verschachtelte Abfragen unterstützt, wenn Sie FOR XML verwenden.
Das Problem hierbei ist nicht die mangelnde Unterstützung durch das RDBMS, sondern die mangelnde Unterstützung von verschachtelten Tabellen in Tabellen.
Was hindert Sie außerdem daran, eine innere Verknüpfung zu verwenden?
Sie können den inneren Join tatsächlich als verschachtelte Tabelle betrachten. Es wird immer nur der Inhalt der ersten beiden Felder wiederholt. Ich würde mir keine großen Sorgen um die Leistung des Joins machen. Der einzige langsame Teil einer solchen Abfrage ist das io von der Datenbank zum Client. Dies ist nur dann ein Problem, wenn der Inhalt eine große Datenmenge enthält. In diesem Fall würde ich zwei Abfragen vorschlagen, eine mit
select id, content
und eine mit einem inneren Join undselect posts.id, comments.*
. Dies skaliert sogar mit mehreren Posts, da Sie immer noch nur 2 Abfragen verwenden würden.quelle
for xml
.Eigentlich unterstützt Oracle, was Sie wollen, aber Sie müssen die Unterabfrage mit dem Schlüsselwort "cursor" umbrechen. Die Ergebnisse werden über den offenen Cursor abgerufen. In Java werden beispielsweise Kommentare als Ergebnismengen angezeigt. Weitere Informationen hierzu finden Sie in der Oracle-Dokumentation zu "CURSOR Expression".
quelle
Einige unterstützen das Verschachteln (hierarchisch).
Wenn Sie eine Abfrage wünschen, können Sie eine Tabelle haben, die sich selbst referenziert. Einige RDMS unterstützen dieses Konzept. Mit SQL Server können Sie beispielsweise Common Table Expressions (CTEs) für eine hierarchische Abfrage verwenden.
In deinem Fall wären die Posts auf Level 0 und dann wären alle Kommentare auf Level 1.
Die anderen Optionen sind 2 Abfragen oder ein Join mit einigen zusätzlichen Informationen für jeden zurückgegebenen Datensatz (die von anderen erwähnt wurden).
Beispiel für hierarchische:
https://stackoverflow.com/questions/14274942/sql-server-cte-and-recursion-example
In dem obigen Link zeigt EmpLevel die Ebene der Verschachtelung (oder Hierarchie) an.
quelle
Es tut mir leid, ich bin nicht sicher, ob ich Ihr Problem genau verstehe.
In MSSQL können Sie nur 2 SQL-Anweisungen ausführen.
Und es werden gleichzeitig Ihre 2 Ergebnismengen zurückgegeben.
quelle
RDBMs basieren auf Theorie und halten sich an diese Theorie. Dies ermöglicht eine gute Konsistenz und mathematisch nachgewiesene Zuverlässigkeit.
Da das Modell einfach ist und wieder auf der Theorie basiert, ist es für die Menschen einfach, Optimierungen und viele Implementierungen vorzunehmen. Dies ist anders als bei NoSQL, wo jeder etwas anders vorgeht.
Es hat in der Vergangenheit Versuche gegeben, hierarchische Datenbanken zu erstellen, aber IIRC (kann es nicht googeln) gab es Probleme (Zyklen und Gleichheit kommen in den Sinn).
quelle
Sie haben ein spezifisches Bedürfnis. Es wäre vorzuziehen, Daten aus einer Datenbank in dem gewünschten Format zu extrahieren, damit Sie damit machen können, was Sie wollen.
Einige Dinge, die Datenbanken nicht so gut können, sind jedoch nicht unmöglich, sie dafür zu erstellen. Die Formatierung anderen Anwendungen zu überlassen, ist die aktuelle Empfehlung, rechtfertigt jedoch nicht, warum dies nicht möglich ist.
Das einzige Argument, das ich gegen Ihren Vorschlag habe, ist, dass ich mit dieser Ergebnismenge auf eine "SQL" -Weise umgehen kann. Es wäre eine schlechte Idee, ein Ergebnis in der Datenbank zu erstellen und nicht in der Lage zu sein, damit zu arbeiten oder es zu manipulieren. Angenommen, ich habe eine Ansicht erstellt, die so aufgebaut ist, wie Sie es vorgeschlagen haben. Wie kann ich sie in eine andere select-Anweisung einfügen? Datenbanken mögen es, Ergebnisse zu erfassen und Dinge damit zu tun. Wie würde ich es mit einem anderen Tisch verbinden? Wie würde ich Ihre Ergebnismenge mit einer anderen vergleichen?
Dann ist der Vorteil von RDMS die Flexibilität von SQL. Die Syntax zum Auswählen von Daten aus einer Tabelle kommt einer Liste von Benutzern oder anderen Objekten im System ziemlich nahe (zumindest das ist das Ziel.). Ich bin mir nicht sicher, ob es Sinn macht, etwas völlig anderes zu tun. Sie haben sie noch nicht einmal dazu gebracht, Prozedurcode / Cursor oder BLOBS von Daten sehr effizient zu handhaben.
quelle
Meiner Meinung nach liegt dies hauptsächlich an SQL und der Art und Weise, wie aggregierte Abfragen ausgeführt werden. Aggregatfunktionen und Gruppierungen werden für große zweidimensionale Rowsets ausgeführt, um Ergebnisse zurückzugeben. So war es von Anfang an und es ist sehr schnell (die meisten NoSQL-Lösungen sind bei der Aggregation recht langsam und stützen sich auf denormalisierte Schemata anstelle komplexer Abfragen).
Natürlich hat PostgreSQL einige Funktionen aus der objektorientierten Datenbank. Entsprechend dieser E-Mails ( Nachricht ) können Sie das erreichen, was Sie benötigen, indem Sie ein benutzerdefiniertes Aggregat erstellen.
Persönlich verwende ich Frameworks wie Doctrine ORM (PHP), die die Aggregation auf der Anwendungsseite durchführen und Funktionen wie das verzögerte Laden unterstützen, um die Leistung zu steigern.
quelle
PostgreSQL unterstützt eine Vielzahl strukturierter Datentypen, einschließlich Arrays und JSON . Mit SQL oder einer der eingebetteten prozeduralen Sprachen können Sie Werte mit beliebig komplexer Struktur erstellen und an Ihre Anwendung zurückgeben. Sie können auch Tabellen mit Spalten eines beliebigen strukturierten Typs erstellen. Sie sollten jedoch sorgfältig prüfen, ob Sie Ihr Design unnötig denormalisieren.
quelle