SELECT * FROM t1
WHERE JSON_EXTRACT(data,"$.series") IN ...
L'utilisation d'une colonne à l'intérieur d'une expression ou d'une fonction comme celle-ci gâche toute chance que la requête utilise un index pour aider à optimiser la requête. La requête ci-dessus est obligée d'effectuer un balayage de table.
L'allégation d'« accès efficace » est trompeuse. Cela signifie qu'après que la requête a examiné une ligne avec un document JSON, elle peut extraire un champ sans avoir à analyser le texte de la syntaxe JSON. Mais il faut toujours un balayage de table pour rechercher des lignes. En d'autres termes, la requête doit examiner chaque ligne.
Par analogie, si je cherche dans l'annuaire téléphonique des personnes dont le prénom est "Bill", je dois toujours lire chaque page de l'annuaire téléphonique, même si les prénoms ont été surlignés pour les repérer un peu plus rapidement.
MySQL 5.7 vous permet de définir une colonne virtuelle dans la table, puis de créer un index sur la colonne virtuelle.
ALTER TABLE t1
ADD COLUMN series AS (JSON_EXTRACT(data, '$.series')),
ADD INDEX (series);
Ensuite, si vous interrogez la colonne virtuelle, elle peut utiliser l'index et éviter le balayage de table.
SELECT * FROM t1
WHERE series IN ...
C'est bien, mais cela manque un peu l'intérêt d'utiliser JSON. La partie intéressante de l'utilisation de JSON est qu'elle vous permet d'ajouter de nouveaux attributs sans avoir à faire ALTER TABLE. Mais il s'avère que vous devez de toute façon définir une colonne supplémentaire (virtuelle) si vous souhaitez rechercher des champs JSON à l'aide d'un index.
Mais vous n'êtes pas obligé de définir des colonnes et des index virtuels pour chaque champ dans le document JSON—uniquement ceux que vous souhaitez rechercher ou trier. Il pourrait y avoir d'autres attributs dans le JSON que vous n'avez qu'à extraire dans la liste de sélection comme suit :
SELECT JSON_EXTRACT(data, '$.series') AS series FROM t1
WHERE <other conditions>
Je dirais généralement que c'est la meilleure façon d'utiliser JSON dans MySQL. Uniquement dans la liste de sélection.
Lorsque vous référencez des colonnes dans d'autres clauses (JOIN, WHERE, GROUP BY, HAVING, ORDER BY), il est plus efficace d'utiliser des colonnes conventionnelles, et non des champs dans des documents JSON.
J'ai présenté une conférence intitulée Comment utiliser JSON dans MySQL Faux à la conférence Percona Live en avril 2018. Je mettrai à jour et répéterai la conférence à Oracle Code One à l'automne.
Il y a d'autres problèmes avec JSON. Par exemple, lors de mes tests, il a fallu 2 à 3 fois plus d'espace de stockage pour les documents JSON par rapport aux colonnes conventionnelles stockant les mêmes données.
MySQL fait la promotion agressive de ses nouvelles capacités JSON, principalement pour dissuader les gens de migrer vers MongoDB. Mais le stockage de données orienté document comme MongoDB est fondamentalement un moyen non relationnel d'organiser les données. C'est différent du relationnel. Je ne dis pas que l'un est meilleur que l'autre, c'est juste une technique différente, adaptée à différents types de requêtes.
Vous devez choisir d'utiliser JSON lorsque JSON rend vos requêtes plus efficaces.
Ne choisissez pas une technologie simplement parce qu'elle est nouvelle ou pour la mode.
Edit:L'implémentation de la colonne virtuelle dans MySQL est censée utiliser l'index si votre clause WHERE utilise exactement la même expression que la définition de la colonne virtuelle. Autrement dit, ce qui suit devrait utiliser l'index sur la colonne virtuelle, puisque la colonne virtuelle est définie AS (JSON_EXTRACT(data,"$.series"))
SELECT * FROM t1
WHERE JSON_EXTRACT(data,"$.series") IN ...
Sauf que j'ai trouvé en testant cette fonctionnalité que cela ne fonctionne PAS pour une raison quelconque si l'expression est une fonction d'extraction JSON. Cela fonctionne pour d'autres types d'expressions, mais pas pour les fonctions JSON. MISE À JOUR :cela fonctionnerait, enfin, dans MySQL 5.7.33.