Mysql
 sql >> Database >  >> RDS >> Mysql

Supporto JSON nativo in MYSQL 5.7:quali sono i pro ei contro del tipo di dati JSON in MYSQL?

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

L'utilizzo di una colonna all'interno di un'espressione o di una funzione come questa annulla ogni possibilità che la query utilizzi un indice per ottimizzare la query. La query mostrata sopra è forzata a eseguire una scansione della tabella.

L'affermazione sull'"accesso efficiente" è fuorviante. Significa che dopo che la query ha esaminato una riga con un documento JSON, può estrarre un campo senza dover analizzare il testo della sintassi JSON. Ma è comunque necessaria una scansione della tabella per cercare le righe. In altre parole, la query deve esaminare ogni riga.

Per analogia, se sto cercando in una rubrica le persone con il nome "Bill", devo comunque leggere ogni pagina della rubrica, anche se i nomi sono stati evidenziati per renderli leggermente più veloci.

MySQL 5.7 ti consente di definire una colonna virtuale nella tabella e quindi creare un indice sulla colonna virtuale.

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

Quindi, se esegui una query sulla colonna virtuale, questa può utilizzare l'indice ed evitare la scansione della tabella.

SELECT * FROM t1
WHERE series IN ...

Questo è carino, ma in qualche modo manca il punto di usare JSON. La parte interessante dell'utilizzo di JSON è che ti consente di aggiungere nuovi attributi senza dover eseguire ALTER TABLE. Ma si scopre che devi comunque definire una colonna (virtuale) extra, se vuoi cercare campi JSON con l'aiuto di un indice.

Ma non è necessario definire colonne e indici virtuali per ogni campo nel documento JSON, solo quelli in cui desideri eseguire la ricerca o l'ordinamento. Potrebbero esserci altri attributi nel JSON che devi solo estrarre nell'elenco di selezione come il seguente:

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

In genere direi che questo è il modo migliore per utilizzare JSON in MySQL. Solo nell'elenco di selezione.

Quando fai riferimento a colonne in altre clausole (JOIN, WHERE, GROUP BY, HAVING, ORDER BY), è più efficiente utilizzare colonne convenzionali, non campi all'interno di documenti JSON.

Ho presentato un discorso chiamato Come utilizzare JSON in MySQL Sbagliato alla conferenza Percona Live nell'aprile 2018. Aggiornerò e ripeterò il discorso a Oracle Code One in autunno.

Ci sono altri problemi con JSON. Ad esempio, nei miei test ha richiesto 2-3 volte più spazio di archiviazione per i documenti JSON rispetto alle colonne convenzionali che memorizzano gli stessi dati.

MySQL sta promuovendo le sue nuove funzionalità JSON in modo aggressivo, principalmente per dissuadere le persone dal migrare a MongoDB. Ma l'archiviazione dei dati orientata ai documenti come MongoDB è fondamentalmente un modo non relazionale di organizzare i dati. È diverso da relazionale. Non sto dicendo che una sia migliore dell'altra, è solo una tecnica diversa, adatta a diversi tipi di query.

Dovresti scegliere di utilizzare JSON quando JSON rende le tue query più efficienti.

Non scegliere una tecnologia solo perché è nuova o per amore della moda.

Modifica:l'implementazione della colonna virtuale in MySQL dovrebbe utilizzare l'indice se la tua clausola WHERE utilizza esattamente la stessa espressione della definizione della colonna virtuale. Cioè, quanto segue dovrebbe utilizzare l'indice sulla colonna virtuale, poiché la colonna virtuale è definita AS (JSON_EXTRACT(data,"$.series"))

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

Tranne che ho scoperto testando questa funzione che NON funziona per qualche motivo se l'espressione è una funzione di estrazione JSON. Funziona con altri tipi di espressioni, non solo con le funzioni JSON. AGGIORNAMENTO:secondo quanto riferito, funziona, finalmente, in MySQL 5.7.33.