SELECT * FROM t1
WHERE JSON_EXTRACT(data,"$.series") IN ...
Usar uma coluna dentro de uma expressão ou função como essa estraga qualquer chance de a consulta usar um índice para ajudar a otimizar a consulta. A consulta mostrada acima é forçada a fazer uma varredura de tabela.
A afirmação sobre "acesso eficiente" é enganosa. Isso significa que depois que a consulta examina uma linha com um documento JSON, ela pode extrair um campo sem precisar analisar o texto da sintaxe JSON. Mas ainda é preciso uma varredura de tabela para procurar linhas. Em outras palavras, a consulta deve examinar todas as linhas.
Por analogia, se estou procurando em uma lista telefônica por pessoas com o primeiro nome "Bill", ainda tenho que ler todas as páginas da lista telefônica, mesmo que os primeiros nomes tenham sido destacados para torná-los um pouco mais rápidos.
O MySQL 5.7 permite definir uma coluna virtual na tabela e, em seguida, criar um índice na coluna virtual.
ALTER TABLE t1
ADD COLUMN series AS (JSON_EXTRACT(data, '$.series')),
ADD INDEX (series);
Então, se você consultar a coluna virtual, ela poderá usar o índice e evitar a verificação da tabela.
SELECT * FROM t1
WHERE series IN ...
Isso é bom, mas meio que perde o objetivo de usar JSON. A parte atraente de usar JSON é que ele permite adicionar novos atributos sem precisar fazer ALTER TABLE. Mas acontece que você precisa definir uma coluna extra (virtual) de qualquer maneira, se quiser pesquisar campos JSON com a ajuda de um índice.
Mas você não precisa definir colunas e índices virtuais para todos campo no documento JSON - apenas aqueles que você deseja pesquisar ou classificar. Pode haver outros atributos no JSON que você só precisa extrair na lista de seleção como o seguinte:
SELECT JSON_EXTRACT(data, '$.series') AS series FROM t1
WHERE <other conditions>
Eu geralmente diria que esta é a melhor maneira de usar JSON no MySQL. Apenas na lista de seleção.
Quando você faz referência a colunas em outras cláusulas (JOIN, WHERE, GROUP BY, HAVING, ORDER BY), é mais eficiente usar colunas convencionais, não campos em documentos JSON.
Eu apresentei uma palestra chamada How to Use JSON in MySQL Errado na conferência Percona Live em abril de 2018. Vou atualizar e repetir a palestra no Oracle Code One no outono.
Existem outros problemas com JSON. Por exemplo, em meus testes, foi necessário 2 a 3 vezes mais espaço de armazenamento para documentos JSON em comparação com colunas convencionais que armazenam os mesmos dados.
O MySQL está promovendo seus novos recursos JSON de forma agressiva, principalmente para dissuadir as pessoas contra a migração para o MongoDB. Mas o armazenamento de dados orientado a documentos, como o MongoDB, é fundamentalmente uma maneira não relacional de organizar dados. É diferente de relacional. Não estou dizendo que um é melhor que o outro, é apenas uma técnica diferente, adequada para diferentes tipos de consultas.
Você deve optar por usar JSON quando o JSON tornar suas consultas mais eficientes.
Não escolha uma tecnologia apenas porque é nova ou por causa da moda.
Edit:A implementação da coluna virtual no MySQL deve usar o índice se sua cláusula WHERE usar exatamente a mesma expressão que a definição da coluna virtual. Ou seja, o seguinte deve use o índice na coluna virtual, pois a coluna virtual é definida
AS (JSON_EXTRACT(data,"$.series"))
SELECT * FROM t1
WHERE JSON_EXTRACT(data,"$.series") IN ...
Exceto que descobri testando esse recurso que ele NÃO funciona por algum motivo se a expressão for uma função de extração JSON. Funciona para outros tipos de expressões, mas não para funções JSON. ATUALIZAÇÃO:isso supostamente funciona, finalmente, no MySQL 5.7.33.