Native JSON-Unterstützung in MYSQL 5.7: Welche Vor- und Nachteile hat der JSON-Datentyp in MYSQL?

113

In MySQL 5.7 wurde ein neuer Datentyp zum Speichern von JSON-Daten in MySQL- Tabellen hinzugefügt. Es wird offensichtlich eine große Veränderung in MySQL sein. Sie führten einige Vorteile auf

Dokumentvalidierung - In einer JSON-Spalte können nur gültige JSON-Dokumente gespeichert werden, sodass Sie eine automatische Validierung Ihrer Daten erhalten.

Effizienter Zugriff - Noch wichtiger ist, dass ein JSON-Dokument beim Speichern in einer JSON-Spalte nicht als Nur-Text-Wert gespeichert wird. Stattdessen wird es in einem optimierten Binärformat gespeichert, das einen schnelleren Zugriff auf Objektelemente und Array-Elemente ermöglicht.

Leistung - Verbessern Sie die Leistung Ihrer Abfrage, indem Sie Indizes für Werte in den JSON-Spalten erstellen. Dies kann mit „Funktionsindizes“ für virtuelle Spalten erreicht werden.

Komfort - Die zusätzliche Inline-Syntax für JSON-Spalten macht es sehr natürlich, Dokumentabfragen in Ihr SQL zu integrieren. Zum Beispiel (features.feature ist eine JSON-Spalte):SELECT feature->"$.properties.STREET" AS property_street FROM features WHERE id = 121254;

WOW ! Sie enthalten einige großartige Funktionen. Jetzt ist es einfacher, Daten zu bearbeiten. Jetzt ist es möglich, komplexere Daten in Spalten zu speichern. So ist MySQL jetzt mit NoSQL gewürzt.

Jetzt kann ich mir eine Abfrage nach JSON-Daten vorstellen

SELECT * FROM t1
WHERE JSON_EXTRACT(data,"$.series") IN 
( 
SELECT JSON_EXTRACT(data,"$.inverted") 
FROM t1 | {"series": 3, "inverted": 8} 
WHERE JSON_EXTRACT(data,"$.inverted")<4 );

Kann ich also große kleine Beziehungen in wenigen json colum speichern? Ist es gut? Bricht es die Normalisierung? Wenn dies möglich ist, wird es sich vermutlich wie NoSQL in einer MySQL-Spalte verhalten . Ich möchte wirklich mehr über diese Funktion erfahren. Vor- und Nachteile des Datentyps MySQL JSON.

Imran
quelle
Oh, bitte sag nicht, was ich denke, dass du sagst. Hier, lies das . Ihre ist noch eine andere Variante einer schlechten Idee.
Drew
@Drew Du hast eine große Antwort gegeben. Aber es ist nicht meine Frage. Ich möchte nur wissen, dass wir SQL-Regeln überspringen können, wenn wir eine Abfrage für JSON-Daten schreiben. Weil wir nicht viele Tische brauchen
Imran
1
du hast gesagt Now it is possible to store more complex data in column. Seien Sie vorsichtig
Drew
2
Json Datentyp Support Index und Es hat Smart Size: 64K & 4G. Was ist das Problem, wenn ich 2000 Daten speichern und 5 verschachtelte Beschriftungen anstelle von 5 Tabellen mit Beziehung hinzufügen möchte?
Imran
5
"Ich möchte wirklich mehr über diese Funktion erfahren." und "Vor- und Nachteile des MySQL JSON-Datentyps". sind keine Fragen, und wenn sie als Fragen umformuliert werden, sind sie zu weit gefasst. "Ich denke also nie an eine komplexe Schemastruktur und Fremdschlüssel in MySQL. Ich speichere komplexe Beziehungen mit nur wenigen Tabellen." ist selbst widersprüchlich, da JSON keine Relationen & FKs sind. Eine Erklärung von "ist das gut" ist nur eine Einführung in das relationale Modell, daher ist dies wiederum zu weit gefasst. Arbeiten Sie einige Beispiele durch, erstellen Sie eine eigene Liste mit Vor- und Nachteilen mit Referenzen und fragen Sie, wo Sie einen Fehler gemacht haben.
Philipip

Antworten:

55
SELECT * FROM t1
WHERE JSON_EXTRACT(data,"$.series") IN ...

Die Verwendung einer Spalte in einem Ausdruck oder einer solchen Funktion beeinträchtigt die Wahrscheinlichkeit, dass die Abfrage mithilfe eines Index zur Optimierung der Abfrage verwendet wird. Die oben gezeigte Abfrage muss einen Tabellenscan durchführen.

Die Behauptung über "effizienten Zugang" ist irreführend. Dies bedeutet, dass die Abfrage, nachdem sie eine Zeile mit einem JSON-Dokument untersucht hat, ein Feld extrahieren kann, ohne den Text der JSON-Syntax analysieren zu müssen. Die Suche nach Zeilen erfordert jedoch immer noch einen Tabellenscan. Mit anderen Worten, die Abfrage muss jede Zeile untersuchen.

Wenn ich in einem Telefonbuch nach Personen mit dem Vornamen "Bill" suche, muss ich analog dazu immer noch jede Seite im Telefonbuch lesen, auch wenn die Vornamen hervorgehoben wurden, damit sie etwas schneller erkannt werden.

Mit MySQL 5.7 können Sie eine virtuelle Spalte in der Tabelle definieren und anschließend einen Index für die virtuelle Spalte erstellen.

ALTER TABLE t1
  ADD COLUMN series AS (JSON_EXTRACT(data, '$.series')),
  ADD INDEX (series);

Wenn Sie dann die virtuelle Spalte abfragen, kann sie den Index verwenden und den Tabellenscan vermeiden.

SELECT * FROM t1
WHERE series IN ...

Das ist schön, aber es verfehlt den Sinn der Verwendung von JSON. Der attraktive Teil der Verwendung von JSON besteht darin, dass Sie neue Attribute hinzufügen können, ohne ALTER TABLE ausführen zu müssen. Es stellt sich jedoch heraus, dass Sie trotzdem eine zusätzliche (virtuelle) Spalte definieren müssen, wenn Sie JSON-Felder mithilfe eines Index durchsuchen möchten.

Sie müssen jedoch nicht für jedes Feld im JSON-Dokument virtuelle Spalten und Indizes definieren - nur für diejenigen, nach denen Sie suchen oder sortieren möchten. Es kann andere Attribute im JSON geben, die Sie nur in der Auswahlliste extrahieren müssen, wie die folgenden:

SELECT JSON_EXTRACT(data, '$.series') AS series FROM t1
WHERE <other conditions>

Ich würde allgemein sagen, dass dies der beste Weg ist, JSON in MySQL zu verwenden. Nur in der Auswahlliste.

Wenn Sie auf Spalten in anderen Klauseln verweisen (JOIN, WHERE, GROUP BY, HAVING, ORDER BY), ist es effizienter, herkömmliche Spalten zu verwenden, keine Felder in JSON-Dokumenten.

Ich habe auf der Percona Live-Konferenz im April 2018 einen Vortrag mit dem Titel " Verwendung von JSON in MySQL Wrong" gehalten. Ich werde den Vortrag im Herbst bei Oracle Code One aktualisieren und wiederholen.

Es gibt andere Probleme mit JSON. In meinen Tests war beispielsweise 2-3 Mal so viel Speicherplatz für JSON-Dokumente erforderlich wie für herkömmliche Spalten, in denen dieselben Daten gespeichert sind.

MySQL fördert seine neuen JSON-Funktionen aggressiv, um Menschen von einer Migration auf MongoDB abzubringen. Die dokumentenorientierte Datenspeicherung wie MongoDB ist jedoch grundsätzlich eine nicht relationale Methode zur Organisation von Daten. Es ist anders als relational. Ich sage nicht, dass eines besser ist als das andere, es ist nur eine andere Technik, die für verschiedene Arten von Abfragen geeignet ist.

Sie sollten JSON verwenden, wenn JSON Ihre Abfragen effizienter macht.

Wählen Sie keine Technologie, nur weil sie neu ist oder der Mode zuliebe.


Bearbeiten: Die Implementierung der virtuellen Spalte in MySQL soll den Index verwenden, wenn Ihre WHERE-Klausel genau den gleichen Ausdruck wie die Definition der virtuellen Spalte verwendet. Das heißt, im Folgenden sollte der Index für die virtuelle Spalte verwendet werden, da die virtuelle Spalte definiert istAS (JSON_EXTRACT(data,"$.series"))

SELECT * FROM t1
WHERE JSON_EXTRACT(data,"$.series") IN ...

Außer ich habe beim Testen dieser Funktion festgestellt, dass sie aus irgendeinem Grund NICHT funktioniert, wenn der Ausdruck eine JSON-Extraktionsfunktion ist. Es funktioniert für andere Arten von Ausdrücken, nur nicht für JSON-Funktionen.

Bill Karwin
quelle
7
Es lohnt sich, dem Link zu den Folien zu folgen
Paul Campbell
Guter Punkt, die beiden Technologien sind beide gut für sich. Wir entscheiden, welche unseren Anforderungen entsprechen und was uns mehr Vorteile in Bezug auf Sicherheit und Leistung verschafft.
Christopher Pelayo
1
Der Kern des Problems besteht darin, dass ALTER TABLE weiterhin benötigt wird, um für jeden neuen Schlüssel im JSON einen Index für eine generierte Spalte zu verwenden. Ich bin froh zu sehen, dass darauf hingewiesen wird.
user1454926
Nur wenn Sie eine virtuelle Spalte und / oder einen Index hinzufügen müssen. Wenn Sie die JSON-Daten als "Black Box" behandeln und nicht versuchen, Abfragen durchzuführen, die in Unterfeldern in JSON suchen oder sortieren, müssen Sie dies nicht tun. Deshalb empfehle ich JSON zu vermeiden Referenzierung in JOIN, WHEREoder anderen Klauseln. Rufen Sie einfach die JSON-Spalte in der Auswahlliste ab.
Bill Karwin
Der Link zu den Folien ist unterbrochen, @BillKarwin.
Lakesare
43

Das Folgende aus MySQL 5.7 bringt sexy zurück mit JSON klingt gut für mich:

Die Verwendung des JSON-Datentyps in MySQL bietet zwei Vorteile gegenüber dem Speichern von JSON-Zeichenfolgen in einem Textfeld:

Datenvalidierung. JSON-Dokumente werden automatisch validiert und ungültige Dokumente führen zu einem Fehler. Verbessertes internes Speicherformat. Die JSON-Daten werden in ein Format konvertiert, das einen schnellen Lesezugriff auf die Daten in einem strukturierten Format ermöglicht. Der Server kann Unterobjekte oder verschachtelte Werte nach Schlüssel oder Index suchen, was zusätzliche Flexibilität und Leistung ermöglicht.

...

Spezielle Varianten von NoSQL-Speichern (Dokument-DBs, Schlüsselwertspeicher und Grafik-DBs) sind wahrscheinlich bessere Optionen für ihre spezifischen Anwendungsfälle. Durch Hinzufügen dieses Datentyps können Sie jedoch möglicherweise die Komplexität Ihres Technologie-Stacks reduzieren. Der Preis ist an MySQL-Datenbanken (oder kompatible Datenbanken) gekoppelt. Dies ist jedoch für viele Benutzer kein Problem.

Beachten Sie die Sprache zur Dokumentvalidierung, da dies ein wichtiger Faktor ist. Ich denke, für den Vergleich der beiden Ansätze muss eine Reihe von Tests durchgeführt werden. Diese beiden Wesen:

  1. MySQL mit JSON-Datentypen
  2. MySQL ohne

Das Netz hat ab sofort nur noch flache Slideshares zum Thema MySQL / JSON / Performance von dem, was ich sehe.

Vielleicht kann Ihr Beitrag ein Hub dafür sein. Oder vielleicht ist die Leistung ein nachträglicher Gedanke, nicht sicher, und Sie freuen sich nur darauf, keine Reihe von Tabellen zu erstellen.

Drew
quelle
7
Ein Betrug; Der JSON-Datentyp wird von MySQL-Speichertabellen wie den Datentypen TEXT und BLOB nicht unterstützt. Das heißt, wenn eine temporäre Tabelle erforderlich ist, wird eine festplattenbasierte Tabelle erstellt, nicht Speicher. Einige Fälle, in denen eine temporäre Tabelle verwendet wird, werden hier beschrieben: dev.mysql.com/doc/refman/5.7/en/internal-temporary-tables.html
raiz media
1
@raizmedia Könnten Sie bitte näher erläutern, warum eine festplattenbasierte Tabelle ein Problem im Vergleich zum Speicher darstellt (basierte Tabelle, denke ich)?
Lapin
@lapin Wahrscheinlich aufgrund von Geschwindigkeitsbeschränkungen.
Kleiner Helfer
@LittleHelper Sie können dies vermeiden, wenn Sie einen PCI 4x 40 Gbit / s M.2-Steckplatz verwenden und ein von 40 Gbit / s unterstütztes Laufwerk einsetzen. Dies funktioniert so schnell wie Speicher. Sie können auch ein spezielles Format auf das Laufwerk anwenden, das zum Formatieren des Speichers verwendet wird.
Sergey Romanov
@ SergeyRomanov, [citation required]haben Sie dieses Laufwerk mit dem RAM verglichen ?
Bill Karwin
11

Ich bin kürzlich auf dieses Problem gestoßen und fasse die folgenden Erfahrungen zusammen:

1, Es gibt keine Möglichkeit, alle Fragen zu lösen. 2, Sie sollten den JSON richtig verwenden.

Ein Fall:

Ich habe eine Tabelle mit dem Namen : CustomField, und es müssen zwei Spalten sein: name, fields. nameist eine lokalisierte Zeichenfolge, deren Inhalt wie folgt aussehen sollte:

{
  "en":"this is English name",
  "zh":"this is Chinese name"
   ...(other languages)
}

Und fieldssollte so sein:

[
  {
    "filed1":"value",
    "filed2":"value"
    ...
  },
  {
    "filed1":"value",
    "filed2":"value"
    ...
  }
  ...
]

Wie Sie sehen können, die beide nameund fieldswerden als JSON gespeichert, und es funktioniert!

nameWas kann ich tun , wenn ich diese Tabelle häufig verwende? Verwenden Sie die JSON_CONTAINS, JSON_EXTRACT...? Offensichtlich ist es keine gute Idee mehr, es als JSON zu speichern. Wir sollten es in einer unabhängigen Tabelle speichern : CustomFieldName.

Aus dem obigen Fall denke ich, dass Sie diese Ideen im Auge behalten sollten:

  1. Warum unterstützt MYSQL JSON?
  2. Warum möchten Sie JSON verwenden? Hat Ihre Geschäftslogik das nur gebraucht? Oder gibt es noch etwas?
  3. Sei niemals faul

Vielen Dank

Bruce
quelle
2
Möglicherweise möchten Sie eine VIRTUAL-Spalte verwenden. percona.com/blog/2016/03/07/…
Bell
10

Nach meiner Erfahrung ist die JSON-Implementierung zumindest in MySql 5.7 aufgrund der schlechten Leistung nicht sehr nützlich. Nun, es ist nicht so schlecht für das Lesen von Daten und die Validierung. Die JSON-Modifikation ist mit MySql jedoch 10 bis 20 Mal langsamer als mit Python oder PHP. Stellen wir uns einen sehr einfachen JSON vor:

{ "name": "value" }

Nehmen wir an, wir müssen es in so etwas umwandeln:

{ "name": "value", "newName": "value" }

Sie können mit Python oder PHP ein einfaches Skript erstellen, das alle Zeilen auswählt und einzeln aktualisiert. Sie sind nicht gezwungen, eine große Transaktion dafür durchzuführen, sodass andere Anwendungen die Tabelle parallel verwenden können. Natürlich können Sie auch eine große Transaktion durchführen, wenn Sie möchten, sodass Sie die Garantie erhalten, dass MySql "alles oder nichts" ausführt, aber andere Anwendungen können die Datenbank während der Transaktionsausführung höchstwahrscheinlich nicht verwenden.

Ich habe 40 Millionen Zeilen Tabelle, und Python-Skript aktualisiert es in 3-4 Stunden.

Jetzt haben wir MySql JSON, also brauchen wir kein Python oder PHP mehr, wir können so etwas tun:

UPDATE `JsonTable` SET `JsonColumn` = JSON_SET(`JsonColumn`, "newName", JSON_EXTRACT(`JsonColumn`, "name"))

Es sieht einfach und ausgezeichnet aus. Die Geschwindigkeit ist jedoch 10 bis 20 Mal langsamer als bei der Python-Version und es handelt sich um eine einzelne Transaktion, sodass andere Anwendungen die Tabellendaten nicht parallel ändern können.

Wenn wir also nur den JSON-Schlüssel in einer Tabelle mit 40 Millionen Zeilen duplizieren möchten, müssen wir die Tabelle 30-40 Stunden lang überhaupt nicht verwenden. Es hat keinen Sinn.

Über das Lesen von Daten ist meiner Erfahrung nach der direkte Zugriff auf das JSON-Feld über JSON_EXTRACTin WHEREauch extrem langsam (viel langsamer als TEXTbei einer LIKEnicht indizierten Spalte). Virtuell generierte Spalten arbeiten viel schneller. Wenn wir jedoch unsere Datenstruktur im Voraus kennen, benötigen wir kein JSON, sondern können stattdessen herkömmliche Spalten verwenden. Wenn wir JSON dort verwenden, wo es wirklich nützlich ist, dh wenn die Datenstruktur unbekannt ist oder sich häufig ändert (z. B. benutzerdefinierte Plugin-Einstellungen), ist die regelmäßige Erstellung virtueller Spalten für mögliche neue Spalten keine gute Idee.

Python und PHP machen die JSON-Validierung zu einem Zauber, daher ist es fraglich, ob wir überhaupt eine JSON-Validierung auf MySQL-Seite benötigen. Warum nicht auch XML, Microsoft Office-Dokumente validieren oder die Rechtschreibung überprüfen? ;)

Vitalii
quelle