Existe-t-il une différence de performances entre ces deux exemples de requêtes?
Requête 1:
select count(*)
from table1 a
join table2 b
on b.key_col=a.key_col
where b.tag = 'Y'
Requête 2;
select count(*)
from table1 a
join table2 b
on b.key_col=a.key_col
and b.tag = 'Y'
Notez que la seule différence est le placement de la condition supplémentaire; le premier utilise une WHERE
clause et le second ajoute la condition à la ON
clause.
Lorsque j'exécute ces requêtes sur mon système Teradata, les plans d'explication sont identiques et l'étape JOIN affiche la condition supplémentaire dans chaque cas. Cependant, sur cette question SO concernant MySQL, l'une des réponses a suggéré que le deuxième style est préféré car le WHERE
traitement se produit après les jointures.
Y a-t-il une règle générale à suivre lors du codage de requêtes comme celle-ci? Je suppose que cela doit dépendre de la plate-forme car cela ne fait évidemment aucune différence sur ma base de données, mais c'est peut-être juste une fonctionnalité de Teradata. Et si cela dépend de la plate - forme, j'aimerais beaucoup obtenir quelques références de documentation; Je ne sais vraiment pas quoi chercher.
la source
Réponses:
Selon le chapitre 9 (analyseur et optimiseur), page 172 du livre Comprendre les composants internes de MySQL par Sasha Pachev
voici la répartition de l'évaluation d'une requête selon les tâches suivantes:
ORDER BY
etGROUP BY
.Sur cette même page, il dit ce qui suit:
ÉPILOGUE
En raison des clés présentes, de la quantité de données et de l'expression de la requête, les jointures MySQL peuvent parfois faire des choses pour notre propre bien (ou pour nous revenir) et produire des résultats que nous ne nous attendions pas et ne pouvons pas expliquer rapidement.
J'ai écrit sur cette bizarrerie avant
Jan 23, 2013
: Problème avec les requêtes UPDATE imbriquéesFeb 22, 2011
: Problème avec la sous-requête MySQLparce que MySQL Query Optimizer pourrait faire ignorer certaines clés lors de l'évaluation de la requête.
Le commentaire de @ Phil m'aide à voir comment publier cette réponse (+1 pour le commentaire de @ Phil)
Le commentaire de @ ypercube (+1 pour celui-ci aussi) est une version compacte de mon article car l'optimiseur de requêtes de MySQL est primitif. Malheureusement, cela doit être le cas puisqu'il s'agit de moteurs de stockage extérieurs.
CONCLUSION
En ce qui concerne votre question réelle, l'optimiseur de requêtes MySQL déterminerait les mesures de performances de chaque requête lorsqu'elle sera effectuée
Vous devrez probablement contraindre l'ordre d'exécution en réécrivant (refactorisant) la requête
Voici la première requête que vous avez donnée
Essayez de le réécrire pour évaluer le WHERE en premier
Cela modifierait certainement le plan EXPLAIN. Cela pourrait produire des résultats meilleurs ou pires.
J'ai déjà répondu à une question dans StackOverflow où j'ai appliqué cette technique. L'EXPLAIN était horrible mais la performance était de la dynamite. Cela n'a fonctionné qu'en raison de la présence des index corrects et de l'utilisation de LIMIT dans une sous-requête .
Comme pour les cours des actions, lorsqu'il s'agit de requêtes et d'essayer de les exprimer, des restrictions s'appliquent, les résultats peuvent varier et les performances passées ne sont pas indicatives des résultats futurs.
la source
Pour Oracle, étant donné que mySQL avait une longue description, nous avons deux façons de tirer parti de l'optimiseur.
Le premier est l'optimisation basée sur les règles (ou RBO). Oracle dispose de 15 règles prédéfinies que chaque requête qu'il analyse tente de suivre dans un ordre défini. S'il ne peut pas générer de requête optimisée à partir de la règle 1, il avancera vers la règle 2 et ensuite jusqu'à ce qu'il atteigne la règle 15.
pour plus d'informations: https://docs.oracle.com/cd/B10500_01/server.920/a96533/rbo.htm
Ceux-ci affectent les noyaux Oracle RDBMS à partir de 11.1 et inférieurs qui n'ont pas été convertis en Cost Based Optimizer (aka CBO). Oracle 11.2 et les versions ultérieures nécessitent l'optimiseur CBO, mais peuvent forcer des ID SQL spécifiques à optimiser dans l'ancienne méthode RBO si l'utilisateur le souhaite.
Le CBO pour Oracle 11.1+ effectue à la place plusieurs plans d'exécution pour le même ID SQL et exécute celui dont le coût global est le moins attendu. Il exploite une grande partie de la logique de RBO, mais analyse les statistiques des tableaux pour créer des coûts de plan d'exécution dynamiques pour chaque opération que la base de données doit faire pour fournir à l'utilisateur final ses données. L'exécution d'analyses de table complètes sur de très grandes tables est très coûteuse; exécuter des analyses de table complètes sur une table à 10 lignes est bon marché. En RBO, ces opérations étaient considérées comme des opérations égales.
pour plus d'informations: https://oracle-base.com/articles/misc/cost-based-optimizer-and-database-statistics
Pour votre exemple de requête spécifique: Oracle analyserait probablement les informations pour faire différents plans d'exécution et donc l'un sera techniquement meilleur que l'autre. Cependant, cela peut être une différence minime. À l'œil nu, Oracle RBO et CBO souhaiteraient la requête 1 de plus, car elle s'exécute sur une jointure dans moins de conditions, puis filtre une colonne spécifique de la table temporaire créée à partir de la jointure.
la source
Si vous avez deux requêtes et que vous pensez qu'elles sont équivalentes, les événements suivants peuvent se produire:
il existe différents plans d'exécution. Nous avons deux sous-cas ici.
2.1 Les requêtes ont des plans d'exécution différents mais les deux plans fonctionnent tout aussi bien. C'est bien aussi. Il n'est pas nécessaire que pour des requêtes équivalentes, le même plan soit généré. Mais les performances doivent être égales. Et encore une fois, nous espérons que c'est le meilleur possible.
2.2 Les requêtes ont des plans d'exécution différents et un plan est meilleur que l'autre. Encore une fois, nous avons des sous-cas:
2.2.1 Les plans sont différents car les requêtes ne sont pas équivalentes. Vérifiez donc attentivement si elles sont vraiment équivalentes. Dans votre cas, ils sont vraiment équivalents.
2.2.2 Les plans sont différents mais les requêtes sont équivalentes. Cela signifie que l'optimiseur n'est pas suffisamment mûr. Dans un monde parfait avec des optimiseurs parfaits, cela ne devrait pas se produire. Alors oui, cela dépend de la plateforme et vous devez étudier des documents spécifiques à la plateforme pour savoir pourquoi cela se produit.
2.2.3 Les plans sont différents, les requêtes sont équivalentes, le logiciel de base de données a un bug.
la source