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.