it-swarm.com.de

Speichern von JSON in der Datenbank gegenüber einer neuen Spalte für jeden Schlüssel

Ich implementiere das folgende Modell zum Speichern von benutzerbezogenen Daten in meiner Tabelle - Ich habe zwei Spalten - uid (Primärschlüssel) und eine meta-Spalte, in der andere Daten des Benutzers im JSON-Format gespeichert werden. 

 uid   | meta
--------------------------------------------------
 1     | {name:['foo'], 
       |  emailid:['[email protected]','[email protected]']}
--------------------------------------------------
 2     | {name:['sann'], 
       |  emailid:['[email protected]','[email protected]']}
--------------------------------------------------

Ist dies ein besserer Weg (leistungsmäßig, designorientiert) als das Einspalten-pro-Eigenschaften-Modell, bei dem die Tabelle viele Spalten wie uid, name, emailid enthält. 

Was mir an dem ersten Modell gefällt, ist, dass Sie so viele Felder wie möglich hinzufügen können. Es gibt keine Einschränkung. 

Außerdem wunderte ich mich jetzt, dass ich das erste Modell implementiert habe. Wie führe ich eine Abfrage aus, z. B. möchte ich alle Benutzer abrufen, deren Name "foo" lautet?

Frage - Welches ist der bessere Weg, benutzerbezogene Daten zu speichern (wobei zu beachten ist, dass die Anzahl der Felder nicht festgelegt ist), wird die Datenbank mit - JSON oder Spalte-pro-Feld verwendet. Wenn das erste Modell implementiert wird, wie kann die Datenbank wie oben beschrieben abgefragt werden? Soll ich beide Modelle verwenden, indem ich alle Daten, die durch eine Abfrage durchsucht werden können, in einer separaten Zeile und die anderen Daten in JSON (ist eine andere Zeile) speichert? 


Aktualisieren

Da es nicht zu viele Spalten gibt, in denen ich suchen muss, ist es sinnvoll, beide Modelle zu verwenden? Schlüssel pro Spalte für die Daten, die ich suchen muss, und JSON für andere Personen (in derselben MySQL-Datenbank)?

146
ShuklaSannidhya

Aktualisiert am 4. Juni 2017

In Anbetracht der Tatsache, dass diese Frage/Antwort an Popularität gewonnen hat, dachte ich, dass es ein Update wert war.

Als diese Frage ursprünglich gestellt wurde, hatte MySQL keine Unterstützung für JSON-Datentypen und die Unterstützung von PostgreSQL steckte noch in den Kinderschuhen. Seit 5.7 ist MySQL unterstützt jetzt einen JSON-Datentyp (in einem binären Speicherformat) und PostgreSQL JSONB ist erheblich ausgereift. Beide Produkte bieten performante JSON-Typen, in denen beliebige Dokumente gespeichert werden können, einschließlich der Unterstützung für die Indizierung bestimmter Schlüssel des JSON-Objekts.

Ich bleibe jedoch bei meiner ursprünglichen Aussage, dass Ihre Standardeinstellung bei Verwendung einer relationalen Datenbank immer noch einen Spaltenwert sein sollte. Relationale Datenbanken basieren immer noch auf der Annahme, dass die darin enthaltenen Daten ziemlich normalisiert werden. Der Abfrageplaner bietet beim Anzeigen von Spalten bessere Optimierungsinformationen als beim Anzeigen von Schlüsseln in einem JSON-Dokument. Fremdschlüssel können zwischen Spalten erstellt werden (jedoch nicht zwischen Schlüsseln in JSON-Dokumenten). Wichtig: Wenn der Großteil Ihres Schemas volatil genug ist, um die Verwendung von JSON zu rechtfertigen, möchten Sie möglicherweise mindestens prüfen, ob eine relationale Datenbank die richtige Wahl ist.

Allerdings sind nur wenige Anwendungen perfekt relational oder dokumentorientiert. Die meisten Anwendungen haben eine Mischung aus beiden. Hier einige Beispiele, bei denen ich persönlich JSON in einer relationalen Datenbank als nützlich erachtet habe:

  • Beim Speichern von E-Mail-Adressen und Telefonnummern für einen Kontakt ist das Speichern als Werte in einem JSON-Array viel einfacher zu verwalten als mehrere separate Tabellen

  • Speichern beliebiger Schlüssel-/Wert-Benutzereinstellungen (wobei der Wert boolesch, textuell oder numerisch sein kann und Sie keine separaten Spalten für verschiedene Datentypen verwenden möchten)

  • Speichern von Konfigurationsdaten ohne definiertes Schema (wenn Sie Zapier oder IFTTT erstellen und Konfigurationsdaten für jede Integration speichern müssen)

Ich bin mir sicher, dass es auch andere gibt, aber dies sind nur einige Beispiele.

Ursprüngliche Antwort

Wenn Sie wirklich so viele Felder hinzufügen möchten, wie Sie möchten, können Sie eine NoSQL-Lösung wie MongoDB verwenden.

Für relationale Datenbanken: Verwenden Sie eine Spalte pro Wert. Das Einfügen eines JSON-Blobs in eine Spalte macht das Abfragen praktisch unmöglich (und ist schmerzhaft langsam, wenn tatsächlich eine funktionierende Abfrage gefunden wird).

Relationale Datenbanken nutzen Datentypen bei der Indizierung und sollen mit einer normalized - Struktur implementiert werden.

Als Randbemerkung: Dies bedeutet nicht, dass Sie JSON niemals in einer relationalen Datenbank speichern sollten. Wenn Sie echte Metadaten hinzufügen oder wenn Ihr JSON Informationen beschreibt, die nicht abgefragt werden müssen und nur für die Anzeige verwendet werden, ist es möglicherweise übertrieben, für alle Datenpunkte eine eigene Spalte zu erstellen.

153
Colin M

Wie die meisten Dinge "kommt es darauf an". Es ist nicht richtig oder falsch/gut oder schlecht, Daten in Spalten oder JSON zu speichern. Es hängt davon ab, was Sie später damit machen müssen. Was ist Ihre voraussichtliche Zugriffsmöglichkeit auf diese Daten? Müssen Sie andere Daten referenzieren? 

Andere Leute haben ziemlich gut geantwortet, was die technischen Kompromisse sind.

Es gibt nicht viele Leute, die besprochen haben, dass sich Ihre App und Funktionen im Laufe der Zeit entwickeln und wie sich diese Entscheidung zur Datenspeicherung auf Ihr Team auswirkt. 

Da eine der Versuchungen bei der Verwendung von JSON darin besteht, die Migration von Schemata zu vermeiden, ist es sehr einfach, ein weiteres Schlüssel/Wert-Paar in ein JSON-Feld zu integrieren, wenn das Team nicht diszipliniert ist. Es gibt keine Migration dafür, niemand erinnert sich, wofür es steht. Es gibt keine Bestätigung darauf. 

Mein Team verwendete JSON neben traditionellen Kolonnen in Postgres und war anfangs das Beste seit dem Aufschneiden von Brot. JSON war attraktiv und mächtig, bis wir eines Tages erkannten, dass Flexibilität mit Kosten verbunden war und plötzlich ein echter Schmerzpunkt war. Manchmal schleicht sich dieser Punkt sehr schnell ein, und dann wird es schwierig, dies zu ändern, da wir neben dieser Designentscheidung noch viele andere Dinge eingebaut haben.

Überstunden, das Hinzufügen neuer Funktionen und die Daten in JSON führten zu komplizierteren Suchanfragen, als dies bei herkömmlichen Spalten der Fall gewesen wäre. Dann fingen wir an, bestimmte Schlüsselwerte wieder in Spalten zu fischen, um Verknüpfungen und Vergleiche zwischen Werten zu erstellen. Schlechte Idee. Jetzt hatten wir Vervielfältigungen. Ein neuer Entwickler würde an Bord kommen und verwirrt sein? Welchen Wert sollte ich wieder einsparen? Die JSON oder die Spalte?

Die JSON-Felder wurden zu Trödelschubladen für kleine Teile dieses und jenes. Keine Datenvalidierung auf Datenbankebene, keine Konsistenz oder Integrität zwischen Dokumenten. Dadurch wurde die gesamte Verantwortung in die App gesteckt, anstatt die traditionellen Texte auf harte Typ- und Einschränkungsprüfung zu überprüfen.

Im Rückblick erlaubte uns JSON, sehr schnell zu iterieren und etwas aus der Tür zu holen. Es war toll. Nachdem wir jedoch eine bestimmte Teamgröße erreicht hatten, ermöglichte uns seine Flexibilität, uns mit einem langen Seil aus technischen Schulden aufzuhängen, das dann den weiteren Fortschritt der Funktionen verlangsamte. Mit Vorsicht verwenden.

Denken Sie lange und gründlich darüber nach, wie Ihre Daten aussehen. Es ist die Grundlage Ihrer App. Wie werden die Daten im Laufe der Zeit verwendet? Und wie ist es wahrscheinlich zu ändern?

44
Homan

Ich habe es einfach rausgeschmissen, aber WordPress hat eine Struktur für diese Art von Sachen (zumindest war WordPress der erste Ort, an dem ich es beobachtet habe, es ist wahrscheinlich woanders entstanden).

Es erlaubt unbegrenzte Schlüssel und ist schneller zu suchen als mit einem JSON-Blob, aber nicht so schnell wie einige der NoSQL-Lösungen.

uid   |   meta_key    |   meta_val
----------------------------------
1         name            Frank
1         age             12
2         name            Jeremiah
3         fav_food        pizza
.................

EDIT

Zum Speichern der Historie/mehrerer Schlüssel

uid   | meta_id    |   meta_key    |   meta_val
----------------------------------------------------
1        1             name            Frank
1        2             name            John
1        3             age             12
2        4             name            Jeremiah
3        5             fav_food        pizza
.................

und über so etwas abfragen:

select meta_val from `table` where meta_key = 'name' and uid = 1 order by meta_id desc
27
Adam

der Nachteil des Ansatzes ist genau das, was Sie erwähnt haben:

dies macht es SEHR langsam, Dinge zu finden, da Sie jedes Mal eine Textsuche durchführen müssen. 

der Wert pro Spalte entspricht stattdessen der gesamten Zeichenfolge.

Ihr Ansatz (JSON-basierte Daten) eignet sich gut für Daten, nach denen Sie nicht suchen müssen, sondern nur zusammen mit Ihren normalen Daten angezeigt werden.

Bearbeiten: Nur zur Klarstellung gilt das oben für klassische relationale Datenbanken. NoSQL verwendet JSON intern und ist wahrscheinlich die bessere Option, wenn dies das gewünschte Verhalten ist.

13

Grundsätzlich wird das erste von Ihnen verwendete Modell als dokumentenbasierter Speicher bezeichnet. Sie sollten sich die beliebte NoSQL-Dokumentdatenbank wie MongoDB und CouchDB ansehen. Grundsätzlich speichern Sie in dokumentenbasierten Datenbanken Daten in Json-Dateien und können dann diese Json-Dateien abfragen.

Das zweite Modell ist die verbreitete relationale Datenbankstruktur. 

Wenn Sie eine relationale Datenbank wie MySql verwenden möchten, würde ich Ihnen empfehlen, nur das zweite Modell zu verwenden. Es hat keinen Sinn, MySql zu verwenden und Daten wie im ersten Modell zu speichern.

Beantworten Sie Ihre zweite Frage mit Bei Verwendung des ersten Modells können Sie nicht den Namen wie 'foo' abfragen}.

8
Girish

Es scheint, dass Sie hauptsächlich zögern, ein relationales Modell zu verwenden oder nicht.

So wie es aussieht, würde Ihr Beispiel einigermaßen gut zu einem relationalen Modell passen, aber das Problem kann natürlich auftreten, wenn Sie dieses Modell weiterentwickeln müssen.

Wenn Sie nur eine (oder einige vordefinierte) Attributebenen für Ihre Hauptentität (Benutzer) haben, können Sie dennoch ein EAV-Modell (Entity Attribute Value) in einer relationalen Datenbank verwenden. (Dies hat auch Vor- und Nachteile.)

Wenn Sie damit rechnen, dass Sie weniger strukturierte Werte erhalten, die Sie mit Ihrer Anwendung durchsuchen möchten, ist MySQL möglicherweise nicht die beste Wahl.

Wenn Sie PostgreSQL verwenden, können Sie möglicherweise das Beste aus beiden Welten herausholen. (Dies hängt wirklich von der tatsächlichen Struktur der Daten hier ab ... MySQL ist auch nicht unbedingt die falsche Wahl, und die NoSQL-Optionen können von Interesse sein, ich bin nur Alternativen vorschlagen.)

In der Tat kann PostgreSQL einen Index für (unveränderliche) Funktionen erstellen (was MySQL meines Wissens nicht kann), und in neueren Versionen können Sie PLV8 für die JSON-Daten direkt verwenden Indizes für bestimmte JSON-Funktionen erstellen Elemente von Interesse, die die Geschwindigkeit Ihrer Abfragen bei der Suche nach diesen Daten verbessern würden.

EDIT:

Da es nicht zu viele Spalten gibt, in denen ich suchen muss, ist es ratsam, beide Modelle zu verwenden? Schlüssel pro Spalte für die Daten, die ich suche, und JSON für andere (in derselben MySQL-Datenbank)?

Das Mischen der beiden Modelle ist nicht unbedingt falsch (vorausgesetzt, der zusätzliche Speicherplatz ist vernachlässigbar), aber es kann Probleme verursachen, wenn Sie nicht sicherstellen, dass die beiden Datensätze synchron gehalten werden: Ihre Anwendung darf niemals einen ändern, ohne auch den anderen zu aktualisieren .

Eine gute Möglichkeit, dies zu erreichen, besteht darin, dass ein Trigger die automatische Aktualisierung durchführt, indem eine gespeicherte Prozedur auf dem Datenbankserver ausgeführt wird, wenn eine Aktualisierung oder Einfügung vorgenommen wird. Soweit mir bekannt ist, wird in der Sprache für gespeicherte MySQL-Prozeduren wahrscheinlich keine JSON-Verarbeitung unterstützt. Auch hier sollte PostgreSQL mit PLV8-Unterstützung (und möglicherweise andere RDBMS mit flexibleren Sprachen für gespeicherte Prozeduren) nützlicher sein (die automatische Aktualisierung Ihrer relationalen Spalte mithilfe eines Triggers ähnelt der Aktualisierung eines Index auf dieselbe Weise).

4
Bruno

einige Zeitverknüpfungen auf dem Tisch sind ein Overhead. Sagen wir für OLAP. Wenn ich zwei Tabellen habe, ist eine ORDERS-Tabelle und die andere ist ORDER_DETAILS. Um alle Details der Reihenfolge zu erhalten, müssen wir zwei Tabellen verknüpfen. Dadurch wird die Abfrage langsamer, wenn keine der Zeilen in den Tabellen zunimmt, sagen wir in Millionen oder so weiter Wenn wir JSON-String/Object in den entsprechenden ORDERS-Eintrag hinzufügen, wird JOIN vermieden. Hinzufügen von Berichten wird schneller sein ...

1
Ravindra

kurze antwort sie müssen miteinander vermischen, verwenden sie json für daten, mit denen sie keine beziehungen wie kontaktdaten, adressen und produktvariablen herstellen 

1
Ahmedfraije Aa

Sie versuchen, ein nicht relationales Modell in eine relationale Datenbank einzufügen. Ich denke, Sie sollten besser eine NoSQL-Datenbank wie MongoDB verwenden. Es gibt kein vordefiniertes Schema, das zu Ihrer Anforderung passt, dass die Anzahl der Felder nicht begrenzt ist (siehe das typische MongoDB-Auflistungsbeispiel). In der MongoDB documentation erhalten Sie eine Vorstellung davon, wie Sie Ihre Dokumente abfragen, z.

db.mycollection.find(
    {
      name: 'sann'
    }
)
1
Chris L

Wie andere darauf hingewiesen haben, werden Abfragen langsamer sein. Ich würde vorschlagen, mindestens eine "_ID" -Spalte hinzuzufügen, um stattdessen die Abfrage durchzuführen.

0
Pants