Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como faço para que o MySQL use um INDEX para consulta de visualização?


Como você faz o MySQL usar um índice para uma consulta de exibição? A resposta curta, forneça um índice que o MySQL possa usar.

Nesse caso, o índice ideal é provavelmente um índice de "cobertura":
... ON highscores (player, happened_in, score)

É provável que o MySQL use esse índice e o EXPLAIN mostrará:"Using index" devido ao WHERE player = 24 (um predicado de igualdade na coluna inicial no índice. O GROUP BY happened_id (a segunda coluna no índice), pode permitir que o MySQL otimize isso usando o índice para evitar uma operação de classificação. Incluindo a score coluna no índice permitirá que a consulta seja satisfeita inteiramente a partir do índice, sem ter que visitar (pesquisar) as páginas de dados referenciadas pelo índice.

Essa é a resposta rápida. A resposta mais longa é que é muito improvável que o MySQL use um índice com coluna inicial de happened_id para a consulta de visualização.

Por que a visualização causa um problema de desempenho

Um dos problemas que você tem com a visualização do MySQL é que o MySQL não "empurra" o predicado da consulta externa para a consulta de visualização.

Sua consulta externa especifica WHERE happened_in = 2006 . O otimizador MySQL não considera o predicado quando executa a "consulta de visualização" interna. Essa consulta para a exibição é executada separadamente, antes da consulta externa. O conjunto de resultados da execução dessa consulta é "materializado"; ou seja, os resultados são armazenados como uma tabela MyISAM intermediária. (O MySQL chama isso de "tabela derivada", e esse nome que eles usam faz sentido, quando você entende as operações que o MysQL executa.)

A linha inferior é que o índice que você definiu em happened_in não está sendo usado pelo MySQL quando ele executa a consulta que forma a definição da visão.

Depois que a "tabela derivada" intermediária é criada, ENTÃO a consulta externa é executada, usando essa "tabela derivada" como uma fonte de linha. É quando essa consulta externa é executada que o happened_in = 2006 predicado é avaliado.

Observe que todas as linhas da consulta de visualização são armazenadas, que (no seu caso) é uma linha para CADA valor de happened_in , não apenas aquele em que você especifica um predicado de igualdade na consulta externa.

A forma como as consultas de visualização são processadas pode ser "inesperada" por alguns, e esta é uma razão pela qual o uso de "visualizações" no MySQL pode levar a problemas de desempenho, em comparação com a forma como as consultas de visualização são processadas por outros bancos de dados relacionais.

Melhorar o desempenho da consulta de visualização com um índice de cobertura adequado

Dada sua definição de exibição e sua consulta, o melhor que você obterá seria um método de acesso "Usando índice" para a consulta de exibição. Para conseguir isso, você precisaria de um índice de cobertura, por exemplo.
... ON highscores (player, happened_in, score).

Esse provavelmente será o índice mais benéfico (em termos de desempenho) para sua definição de exibição existente e sua consulta existente. O player column é a coluna principal porque você tem um predicado de igualdade nessa coluna na consulta de exibição. O happened_in A coluna é a próxima, porque você tem uma operação GROUP BY nessa coluna, e o MySQL poderá usar esse índice para otimizar a operação GROUP BY. Também incluímos a score coluna, porque essa é a única outra coluna referenciada em sua consulta. Isso torna o índice um índice de "cobertura", porque o MySQL pode satisfazer essa consulta diretamente das páginas de índice, sem a necessidade de visitar nenhuma página na tabela subjacente. E isso é tão bom quanto vamos sair desse plano de consulta:"Using index" sem "Using filesort".

Compare o desempenho com uma consulta independente sem tabela derivada

Você pode comparar o plano de execução da sua consulta com a visualização com uma consulta independente equivalente:
SELECT player
     , MAX(score) AS highest_score
     , happened_in
 FROM highscores
WHERE player = 24
  AND happened_in = 2006
GROUP
   BY player
    , happened_in

A consulta autônoma também pode fazer uso de um índice de cobertura, por exemplo.
... ON highscores (player, happened_in, score)

mas sem a necessidade de materializar uma tabela MyISAM intermediária.

Não tenho certeza de que qualquer uma das anteriores forneça uma resposta direta à pergunta que você estava fazendo.

P:Como faço para que o MySQL use um INDEX para consulta de visualização?

R:Defina um ÍNDICE adequado que a consulta de visualização possa usar.

A resposta curta é fornecer um "índice de cobertura" (o índice inclui todas as colunas referenciadas na consulta de exibição). As colunas iniciais nesse índice devem ser as colunas referenciadas com predicados de igualdade (no seu caso, a coluna player seria uma coluna inicial porque você tem um player = 24 predicado na consulta. Além disso, as colunas referenciadas no GROUP BY devem ser colunas iniciais no índice, o que permite ao MySQL otimizar o GROUP BY operação, usando o índice em vez de usar uma operação de classificação.

O ponto chave aqui é que a consulta de visualização é basicamente uma consulta independente; os resultados dessa consulta são armazenados em uma tabela "derivada" intermediária (uma tabela MyISAM que é criada quando uma consulta na exibição é executada.

Usar visualizações no MySQL não é necessariamente uma "má ideia", mas eu aconselho fortemente aqueles que optam por usar visualizações no MySQL para estarem cientes de como o MySQL processa as consultas que fazem referência a essas visualizações. E a maneira como o MySQL processa as consultas de visualização difere (significativamente) da maneira como as consultas de visualização são tratadas por outros bancos de dados (por exemplo, Oracle, SQL Server).