Comment obtenir MySQL à utiliser un index pour un affichage requête? La réponse courte, fournir un indice que MySQL peut utiliser.
Dans ce cas, l'optimum de l'indice est susceptible d'une "couverture" de l'index:
... ON highscores (player, happened_in, score)
Il est probable que MySQL va utiliser cet index, et l'EXPLIQUER affichera: "Using index"
en raison de l' WHERE player = 24
(un prédicat d'égalité sur la première colonne de l'index. L' GROUP BY happened_id
(la deuxième colonne de l'index), peut permettre à MySQL pour optimiser ce à l'aide de l'index pour éviter une opération de tri. Y compris l' score
colonne dans l'index permettra à la requête satisfait entièrement à partir de l'index, sans avoir à visiter (recherche) les pages de données référencée par l'index.
C'est de la réponse rapide. La plus longue réponse, c'est que MySQL est très rare d'utiliser un indice de colonne principale de happened_id
pour l'avis de requête.
Pourquoi la vue provoque un problème de performances
L'un des problèmes que vous avez avec MySQL point de vue est que MySQL ne pas "pousser" le prédicat de la requête externe vers le bas dans l'avis de requête.
Votre requête externe spécifie WHERE happened_in = 2006
. L'optimiseur MySQL ne considère pas le prédicat lorsqu'il s'exécute à l'intérieur "de la vue de requête". Cette requête pour le point de vue est exécuté séparément, avant de la requête externe. Le jeu de résultats de l'exécution de cette requête get "matérialisée"; c'est, les résultats sont stockés en tant qu'intermédiaire table MyISAM. (MySQL appelle une "table dérivée", et que le nom qu'ils utilisent un sens, quand vous comprenez les opérations que MysQL fait.)
La ligne de fond est que l'indice que vous avez défini sur happened_in
n'est pas utilisé par MySQL, quand il rusn la requête qui forme la définition de la vue.
Après l'intermédiaire "table dérivée" est créé, ALORS que l'extérieur de la requête est exécutée, l'utilisation de la "table dérivée" en tant que contenu (rowsource). C'est à ce moment que l'extérieur de la requête s'exécute que l' happened_in = 2006
prédicat est évalué.
Notez que toutes les lignes de la vue de requête sont stockées, ce qui (dans votre cas) est une ligne pour CHAQUE valeur de happened_in
, et pas seulement celle que vous spécifiez un prédicat d'égalité dans la requête externe.
La façon à afficher les requêtes sont traitées peuvent être "inattendu" par certains, et c'est une des raisons que l'utilisation de "points de vue" dans MySQL peut entraîner des problèmes de performances, par rapport à la manière d'afficher les requêtes sont traitées par d'autres bases de données relationnelles.
L'amélioration de la performance de l'avis de requête, avec un index de couverture
Compte tenu de votre définition de la vue et de votre requête, sur le meilleur, vous allez l'obtenir serait un "à l'Aide de l'indice de" méthode d'accès pour l'avis de requête. Pour l'obtenir, vous aurez besoin d'un index de couverture, par exemple
... ON highscores (player, happened_in, score).
Qui est susceptible d'être le plus bénéfique (l'indice de la performance sage) de votre définition de la vue et de votre requête existante. L' player
colonne est la colonne principale parce que vous avez un prédicat d'égalité sur la base de cette colonne dans la vue de requête. L' happened_in
colonne est le suivant, parce que vous avez un GROUPE PAR opération sur la colonne, et MySQL va être en mesure d'utiliser cet indice pour optimiser le GROUPE PAR l'opération. Nous avons aussi inclus les score
de la colonne, parce que c'est la seule autre colonne référencée dans votre requête. Que fait l'indice d'une "couverture" de l'index, parce que MySQL peut satisfaire à cette requête directement à partir des pages de l'index, sans avoir besoin de visiter toutes les pages dans la table sous-jacente. Et c'est aussi bien que nous allons sortir de ce plan de requête: "à l'Aide de l'indice de" sans "Using filesort".
Comparer les performances autonome requête sans table dérivée
On pourrait comparer le plan d'exécution de votre requête sur la vue par rapport à l'équivalent autonome de la requête:
SELECT player
, MAX(score) AS highest_score
, happened_in
FROM highscores
WHERE player = 24
AND happened_in = 2006
GROUP
BY player
, happened_in
La version autonome de requête peut également faire usage d'un index de couverture par exemple
... ON highscores (player, happened_in, score)
mais sans avoir besoin de concrétiser un intermédiaire table MyISAM.
Je ne suis pas sûr que la précédente fournit une réponse directe à la question que vous posiez des questions.
Q: Comment puis-je obtenir MySQL à utiliser un INDEX pour afficher la requête?
A: Définir un INDEX adéquat que la vue requête peut utiliser.
La réponse courte est de fournir une "couvrant l'index" (indice inclut toutes les colonnes référencées dans la vue de requête). Les premières colonnes de l'indice doivent être les colonnes qui sont référencés avec des prédicats d'égalité (dans votre cas, la colonne player
serait une colonne principale parce que vous avez un player = 24
prédicat dans la requête. Aussi, les colonnes référencées dans le GROUP BY doit être à la pointe des colonnes dans l'index, ce qui permet de MySQL pour optimiser l' GROUP BY
de l'opération, en faisant usage de l'index plutôt que de recourir à une opération de tri.
Le point clé ici est que l'avis de requête est essentiellement autonome de la requête; les résultats de cette requête et stockés dans un lieu intermédiaire "dérivée" de la table (une table MyISAM qui est créé lorsqu'une requête contre la vue est exécuté.
À l'aide de points de vue dans MySQL n'est pas nécessairement une "mauvaise idée", mais je vous recommande de la prudence ceux qui choisissent d'utiliser des vues au sein de MySQL pour être au COURANT de comment MySQL processus de requêtes qui font référence à ces points de vue. Et la façon dont MySQL processus de requêtes d'affichage diffère (de façon significative) de la manière d'afficher les requêtes sont traitées par d'autres bases de données (par exemple, Oracle, SQL Server).