8
votes

Implications de performance de permettre l'utilisation d'un alias d'avoir une clause

Je me suis fait un peu un imbécile de moi plus tôt aujourd'hui sur Cette question . La question utilisait SQL Server et la réponse correcte impliquait l'ajout d'une clause . L'erreur initiale que j'ai faite était de penser qu'un alias de l'instruction de sélectionner pourrait être utilisé dans la clause , qui n'est pas autorisée dans SQL Server. J'ai fait cette erreur parce que j'ai supposé que SQL Server avait les mêmes règles que MySQL, qui permettent à un alias d'être utilisé dans le ayant clause.

Cela m'a eu curieux, et j'ai goûté sur Dépassement de pile et ailleurs, trouver un tas de matériau expliquant pourquoi ces les règles sont appliquées sur les deux RDBR respectifs. Mais nulle part j'ai trouvé une explication de ce que les performance les implications permettraient de permettre / interdire un alias dans la clause .

donner un béton Exemple, je vais dupliquer la requête qui s'est produite dans la question mentionnée ci-dessus: xxx

quelles seraient les conséquences de la performance de l'utilisation d'un alias dans le ayant Clause au lieu de la spécification du nombre ? Cette question peut répondre directement à MySQL, et j'espère que quelqu'un pourrait donner un aperçu de ce qui se passerait dans SQL si elle devait prendre en charge l'alias dans le ayant clause.

Ceci est une rare instance où il pourrait être correct de baliser une question SQL avec MySQL et SQL Server, alors profitez-en ce moment au soleil.


2 commentaires

Je me fais un imbécile de moi tout le temps.


Dupliqué possible de Paramétrage d'une SQL en clause


3 Réponses :


2
votes

Ceci est trop long pour un commentaire.

Je ne pense pas qu'il n'y ait vraiment aucune implication de performance, à moins que l'expression dans la clause contienne un traitement compliqué (dire, comptage (distinct) ou une fonction complexe ou une fonction complexe. , tels que le traitement des chaînes sur une longue chaîne).

Je suis presque certain que MySQL effectuera la fonction d'agrégation deux fois si elle est mentionnée deux fois dans la requête. Je ne sais pas si SQL Server optimisera la deuxième référence, mais je devinerai non (SQL Server a un bon optimiseur, mais ce n'est pas une si bonne élimination d'expression commune).

La question est alors la complexité de l'expression. Des expressions simples telles que comptent () et somme () vraiment n'encurent pas beaucoup de frais supplémentaires - une fois que l'agrégation est déjà fait. Les expressions complexes pourraient commencer à coûter cher.

Si vous avez une expression complexe dans SQL Server, vous devriez être en mesure de garantir qu'il est évalué une fois en utilisant une sous-requête.


3 commentaires

Donc, il serait donc prudent de dire qu'il est généralement préférable dans MySQL de utiliser un alias dans la clause , supposant qu'il soit possible de le faire?


J'essaie d'évaluer si les frais généraux du calcul d'un alias se reproduisent à nouveau à réévaluer l'expression dans la clause . En d'autres termes, j'espérais que vous pouviez nous faire savoir quelle devrait être la meilleure pratique en ce qui concerne la clause .


@Timbiegeleisen. . . Oui je suis d'accord. Je suis à peu près sûr que le but de permettre à l'alias dans la clause est partiellement basé sur le fait que MySQL matérialise sous-requêtes. Ainsi, une sous-requête n'est pas un bon moyen de définir un calcul complexe (telle que la distance) lorsque vous souhaitez l'utiliser pour filtrer.



1
votes

J'attendais que le SQL se déroule dans l'ordre de à partir de , , groupe par , ayant , sélectionnez , commander par

Je ne suis pas un expert mysql, mais j'ai trouvé cette raison sortie dans le Documentation MySQL sur la raison pour laquelle il est légal.

MySQL étend l'utilisation standard SQL du groupe par de manière à ce que la liste de sélection puisse se référer à des colonnes non protégées non nommées dans le groupe par clause. Cela signifie que la requête précédente est légale dans MySQL. Vous pouvez utiliser cette fonctionnalité pour obtenir de meilleures performances en évitant le tri et le regroupement de colonnes inutiles. Cependant, ceci est utile principalement lorsque toutes les valeurs de chaque colonne non gré non nommée dans le groupe en sont les mêmes pour chaque groupe. Le serveur est libre de choisir n'importe quelle valeur de chaque groupe, de sorte qu'elles soient identiques, les valeurs choisies sont indéterminées. En outre, la sélection des valeurs de chaque groupe ne peut pas être influencée par l'ajout d'une commande par clause. Le tri des résultats des résultats se produit après que les valeurs ont été choisies et que l'ordre n'augmente pas quelles valeurs dans chaque groupe le serveur choisit.

une extension MySQL similaire s'applique à la clause . Dans SQL Standard, une requête ne peut pas se référer à des colonnes non grélées dans la clause de présentation qui ne sont pas nommées dans le groupe par clause. Pour simplifier les calculs, une extension MySQL permet des références à de telles colonnes. Cette extension suppose que les colonnes NongRoupées ont les mêmes valeurs sages de groupe. Sinon, le résultat est indéterminé.

sur l'impact sur la performance, je suppose que, l'aliasement ayant diminué plus lentement que l'indemnité que le filtre doit être appliqué après toute l'exécution. J'attendrai que les experts commenteront.


0 commentaires

4
votes

étroitement axé sur cette requête particulière et avec des données d'échantillonnage chargées ci-dessous. Cela traite d'autres requêtes telles que le nombre (distinct ...) code> mentionné par d'autres.

l'alias dans l'atteinte code> apparaît légèrement surperformer ou assez un peu surperformer son alternative (selon la requête). strong> p>

Ceci utilise Une table préexistante avec environ 5 millions de lignes en elle a créé rapidement via cette Répondre de la mine qui prend 3 à 5 minutes. p>

Structure résultante: p> xxx pré>

mais utiliser innodb à la place. Crée à l'anomalie InnoDB Gap attendue en raison des insertions de réservation de gamme. Je viens de dire, mais ne fait aucune différence. 4,7 millions de lignes. P>

Modifiez la table pour obtenir près du schéma supposé de Tim. P> xxx pré>

Ce qui suit prendra un certain temps. Lancez-le à nouveau et encore dans des morceaux ou bien votre connexion peut trop faire du délai d'attente. Le délai d'attente est due à 5 millions de lignes sans clause limite dans la déclaration de mise à jour. Remarque, nous do em> ont une clause limite. P>

Nous le faisons donc dans un demi-million d'itérations. Définit une colonne sur un nombre aléatoire compris entre 1 et 20 p> xxx pré>

continuez à exécuter ce qui précède jusqu'à ce que non Camid code> est null. p>

Je l'ai couru comme 10 fois (le tout prend 7 à 10 minutes) p> xxx pré>

créer un index utile (après les insertions bien sûr). p>

+----+-------------+----------+-------+---------------+------------+---------+----------------------+--------+----------------------------------------------+
| id | select_type | table    | type  | possible_keys | key        | key_len | ref                  | rows   | Extra                                        |
+----+-------------+----------+-------+---------------+------------+---------+----------------------+--------+----------------------------------------------+
|  1 | SIMPLE      | campus   | index | PRIMARY       | PRIMARY    | 4       | NULL                 |     20 | Using index; Using temporary; Using filesort |
|  1 | SIMPLE      | students | ref   | ix_stu_cam    | ix_stu_cam | 5       | bigtest.campus.camID | 123766 | Using index                                  |
+----+-------------+----------+-------+---------------+------------+---------+----------------------+--------+----------------------------------------------+


0 commentaires