JSON in relationalen Datenbanken

Sempervivum

Erfahrenes Mitglied
Aus gegebenem Anlass möchte ich mal ein Verfahren im Bereich der Datenbanken zur Diskussion stellen, das relativ neu ist, wenig angewendet wird und über eine geringe Akzeptanz verfügt: Das Speichern von Datenstrukturen in einer Spalte einer Tabelle in Form eines JSON-kodierten Strings.

Relationale Datenbanken sind weit verbreitet und gut eingeführt. Sie haben jedoch eine gravierende Beschränkung: Die Struktur der Daten ist auf zwei Dimensionen beschränkt. Häufig ist es jedoch erforderlich, eine dritte Dimension hinein zu bringen, wenn eine Anzahl von gleichartigen Elementen in einem Datensatz gespeichert werden soll. Unerfahrene lösen das häufig, indem getrennte Felder mit einer Nummer als Suffix angelegt werden: element1, element2, element3, usw. Die Nachteile liegen auf der Hand:
Entweder man verschwendet Elemente, wenn man sehr viele anlegt.
Oder die, die man mal angelegt hat, reichen irgend wann nicht mehr aus.
Außerdem ist es nicht möglich, z. B. über die Elemente zu iterieren oder auf ein Element mit dem Index in einer Variablen zuzugreifen.

Die eingeführte Lösung besteht darin, dass man eine weitere unabhängige Tabelle mit diesen Elementen einführt. Hat den Vorteil, dass man auf die Elemente mit einem einfachen Select zugreifen kann, die Anzahl ermitteln, darüber iterieren etc. Jedoch den Nachteil, dass die Zugriffe komplizierter werden, wenn Verknüpfungen zwischen den Tabellen erforderlich sind, es sind Joins oder Subqueries erforderlich. Ebenso die Pflege: Will man von Hand die Elemente ermitteln, die zusammen gehören, wird es ebenfalls kompliziert. Objektiv betrachtet, muss man diese Lösung als Workaround betrachten, um die Beschränkung der Datenbank auf zwei Dimensionen zu umgehen.

Durch das Einführen der JSON-Kodierung von Arrays und komplexeren Strukturen ist jetzt eine elegante und einfache Lösung verfügbar. Diese können problemlos in einem Datensatz untergebracht werden ohne die Probleme, die man früher hatte. Mindestens MySQL und MariaDB unterstützen das ausdrücklich indem sie einen Datentyp JSON bereit stellen. Sollte das nicht der Fall sein, genügt ein Feld vom Datentyp String um die JSON-kodierte Struktur zu speichern.
MySQL :: MySQL 8.4 Reference Manual :: 13.5 The JSON Data Type
JSON Data Type

Es bleibt zu hoffen, dass diese fortschrittliche und elegante Methode in Zukunft größere Anwendung und Akzeptanz findet.

Beste Grüße
Ulrich
 
Pro JSON: Man spart sich i.d.R. eine weitere Tabelle (wie oben beschrieben) mit all ihren zusätzlichen "Komplexitäten". Sollte i.d.R. auch die Performance erhöhen, da nicht mehr ge-JOIN-ed werden muss

Contra JSON:
1) Die Leute sind es einfach aus der langjährigen Anwendung gewohnt, wie die Detail-Sätze zu "manipulieren" (Count Detail-Sätze. Ändern einzelnen Detail-Satz etc.) sind.
Ganz zu schweigen, dass mit den JOIN's sehr gute und sehr komplexe Abfragen möglich sind.
2) Hat man eine grosse Menge an Detail-Sätzen, kann man strategisch die Detail-Tabelle auf eine andere Festplatte/Partition verschieben. Stell ich mir schwierig vor, wenn die Detail-Sätze als JSON zusammengeklopft im Parent-Record mit drin ist

Nur mal was mir auf Anhieb eingefallen ist
 
Ich habe da keine vertiefte Erfahrung damit. Der Vorteil vom verteilen auf Tabellen ist es, dass man über EInzelwerte Filtern, verknüpfen etc kann. Geht das gut mit JSONs in der Tabelle?
 
Danke für die Kommentare und Meinungen.

Die Leute sind es einfach aus der langjährigen Anwendung gewohnt, wie die Detail-Sätze zu "manipulieren" (Count Detail-Sätze. Ändern einzelnen Detail-Satz etc.) sind."
Das läuft auf ein "Haben wir schon immer so gemacht" hinaus, was noch nie ein guter Grund war, etwas zu tun oder nicht zu tun.

Hat man eine grosse Menge an Detail-Sätzen, kann man strategisch die Detail-Tabelle auf eine andere Festplatte/Partition verschieben.
Das trifft zu. Handelt es sich um eine große Anzahl von Elementen je Datensatz würde ich auch nicht unbedingt empfehlen, diese in einem Datensatz abzulegen.

dass mit den JOIN's sehr gute und sehr komplexe Abfragen möglich sind.
Der Vorteil vom verteilen auf Tabellen ist es, dass man über EInzelwerte Filtern, verknüpfen etc kann.
Dazu ist zu sagen, dass ein nicht unerheblicher Teil dieses komplexen Verknüpfens, Filterns etc. überhaupt nur dadurch erforderlich wird, dass die Daten auf mehrere Tabellen aufgeteilt wurden.

Beim konkreten Anlass für diesen Thread:
Check E-mail plus check ...
ging es um ganze 6 Elemente namens "Vote" je Person bzw. Datensatz. Ein überflüssiger Overkill an Komplexität wenn man deswegen eine weitere Tabelle anlegen würde. Bei anderen Anlässen, an die ich mich erinnere, war es ähnlich und es ging um kaum mehr als 10 Elemente.

Beste Grüße
Ulrich
 
Das läuft auf ein "Haben wir schon immer so gemacht" hinaus, was noch nie ein guter Grund war, etwas zu tun oder nicht zu tun.
Stimmt. Sollte keine Entscheidungsgrundlage sein, ist aber "Praxis"
Dazu ist zu sagen, dass ein nicht unerheblicher Teil dieses komplexen Verknüpfens, Filterns etc. überhaupt nur dadurch erforderlich wird, dass die Daten auf mehrere Tabellen aufgeteilt wurden.
Genau da sitzt aber der Hase im Pfeffer. In einer separaten Tabelle kannst du gezielt auf einen Wert filtern, unabhängig davon zu welchem Master-Satz der eigentlich hingehört.
Wobei ich mir sicher bin, dass die DBMS die entsprechenden JSON-Werkzeuge/Funktionen zur Verfügung stellen, nur eben halt nicht so "intuitiv"
Ganz zu schweigen wie das mit JSON geht, wenn man nen Backjoin machen muss (JOIN zurück auf die gleiche Tabelle)

EDIT
Hat man eine grosse Menge an Detail-Sätzen, kann man strategisch die Detail-Tabelle auf eine andere Festplatte/Partition verschieben.
Das trifft zu. Handelt es sich um eine große Anzahl von Elementen je Datensatz würde ich auch nicht unbedingt empfehlen, diese in einem Datensatz abzulegen.
Wobei in so einem Fall man über "Partitioning/Sharding" nachdenken könnte.
Partitioning = Vertikales "Aufteilen" einer Tabelle --> Bsp. Sätze 1-1000 Auf HD1, Sätze 1001-2000 auf HD2 usw.
Sharding = Horizontales "Aufteilen" einer Tabelle --> Bsp. Spalte 1-20 auf HD1, Spalte 11-20 auf HD2 usw.
Sharding ist vom Prinzip her eine "1:1"-Beziehung die direkt vom DBMS gemanaged wird
 
Zuletzt bearbeitet:
Wobei ich mir sicher bin, dass die DBMS die entsprechenden JSON-Werkzeuge/Funktionen zur Verfügung stellen, nur eben halt nicht so "intuitiv"
Das trifft zu, die DBMS stellt sehr viele Funktionen zur Verfügung, um mit JSON zu arbeiten. Ich habe da gerade ein wenig hinein geschnuppert.
"Intuitiv" ist stark von der Ausgangssituation abhängig, ob man in dem Verfahren mit Joins tief verwurzelt ist oder nicht. Für mich selbst trifft letzteres zu und ich empfinde die Arbeit mit JSON wesentlich intuitiver.
 
Weil ich das Thema hoch interessant finde, bin ich dem ein wenig weiter nach gegangen. Ich erinnere mich an ein Projekt, wo es eine Datenbank gab mit Schauspielern und Filmen. Eine n:m-Beziehung weil ein Schauspieler in mehreren Filmen mitgespielt hat und an einem Film mehrere Schauspieler beteiligt waren. Wenn ich richtig informiert bin, besteht die konventionelle Lösung darin, eine Verweistabelle einzuführen, die in beiden Richtungen über die IDs die Beziehung herstellt zwischen der Tabelle mit den Schauspielern und der mit den Filmen.
Beim Einsatz von JSON kann man diese Hilfstabelle einsparen, indem man die IDs der Filme beim Schauspieler in einem JSON-Array ablegt und ebenso in der entgegen gesetzten Richtung. Z. B. hat dann beim Schauspieler ein Feld movies den Inhalt [8,9,10]
Die Abfrage, um die Filme den Schauspielern zuzuordnen, konnte ich dann sehr einfach und intuitiv formulieren:
Code:
SELECT actor.actor, movie2.title, movie2.year, movie2.land
FROM actor LEFT JOIN movie2 ON JSON_CONTAINS(actor.movies, movie2.id, '$')
Mit der Verweistabelle wäre mir das nicht so leicht gefallen und hätte mehr Gedankenarbeit und wahrscheinlich ein weiteres Join gebraucht.
 
Zurück