Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Native JSON-Unterstützung in MYSQL 5.7:Was sind die Vor- und Nachteile des JSON-Datentyps in MYSQL?

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

Die Verwendung einer Spalte innerhalb eines Ausdrucks oder einer solchen Funktion verdirbt jede Chance, dass die Abfrage einen Index verwendet, um die Abfrage zu optimieren. Die oben gezeigte Abfrage wird gezwungen, einen Table-Scan durchzufü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. Es ist jedoch immer noch ein Tabellenscan erforderlich, um nach Zeilen zu suchen. Mit anderen Worten, die Abfrage muss jede Zeile untersuchen.

Wenn ich analog ein Telefonbuch nach Personen mit dem Vornamen "Bill" durchsuche, muss ich trotzdem jede Seite im Telefonbuch lesen, auch wenn die Vornamen hervorgehoben wurden, um sie etwas schneller zu finden.

MySQL 5.7 ermöglicht es Ihnen, eine virtuelle Spalte in der Tabelle zu definieren und dann einen Index für die virtuelle Spalte zu 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 nett, aber es verfehlt irgendwie 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. Aber es stellt sich heraus, dass Sie sowieso eine zusätzliche (virtuelle) Spalte definieren müssen, wenn Sie JSON-Felder mit Hilfe eines Indexes durchsuchen möchten.

Aber Sie müssen nicht für alle virtuelle Spalten und Indizes definieren Feld im JSON-Dokument – ​​nur die, nach denen Sie suchen oder sortieren möchten. Es könnte 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 in anderen Klauseln (JOIN, WHERE, GROUP BY, HAVING, ORDER BY) auf Spalten verweisen, ist es effizienter, herkömmliche Spalten statt Felder in JSON-Dokumenten zu verwenden.

Ich habe einen Vortrag namens How to Use JSON in MySQL gehalten Falsch auf der Percona Live-Konferenz im April 2018. Ich werde den Vortrag bei Oracle Code One im Herbst aktualisieren und wiederholen.

Es gibt andere Probleme mit JSON. Beispielsweise benötigte es in meinen Tests 2-3 Mal so viel Speicherplatz für JSON-Dokumente im Vergleich zu herkömmlichen Spalten, die dieselben Daten speichern.

MySQL bewirbt seine neuen JSON-Fähigkeiten aggressiv, hauptsächlich um Menschen davon abzubringen, zu MongoDB zu migrieren. Aber eine dokumentenorientierte Datenspeicherung wie MongoDB ist im Grunde eine nicht-relationale Art, Daten zu organisieren. Es ist anders als relational. Ich sage nicht, dass eines besser als das andere ist, 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 denselben Ausdruck wie die Definition der virtuellen Spalte verwendet. Das heißt, das Folgende sollte Verwenden Sie den Index für die virtuelle Spalte, da die virtuelle Spalte als AS (JSON_EXTRACT(data,"$.series")) definiert ist

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. UPDATE:das funktioniert angeblich endlich in MySQL 5.7.33.