6
votes

Laquelle de deux façons de coder une join interne est plus rapide?

Je préfère beaucoup à coder dans T-SQL en utilisant ce qui est en vigueur une jointure en ligne plutôt que d'avoir une longue liste des jointures à la fin de la procédure stockée ou de la vue.

Par exemple, I CODE: P>

SELECT t.PKey, t.Billable, c.LastName, m.Description, lt.TaskName, t.StartTime, t.EndTime, t.SavedTime
FROM dbo.TopicLog AS t     
inner join  Contact.dbo.Contacts as c   on  c.Pkey = t.Contacts_PKey and t.StartTime > '7/9/09'
inner join  Common.dbo.LMain  as m  on  m.PKey = t.DType
inner join  Common.dbo.LTask  as lt on lt.PKey = t.TaskType
ORDER BY t.StartTime


0 commentaires

8 Réponses :


20
votes

le second (la jointure interne réelle), généralement. Le premier (sous-requêtes) fait 3 requêtes pour chaque rangée, mais elle est généralement gérée par le compilateur afin que les différences soient atténuées.

meilleur encore: Vérifiez les plans d'exécution de la requête pour vous-même! < / p>

Étant donné que vous obtenez des performances lentes, je suppose que vos tables ne sont pas indexées correctement. Vous devriez avoir des index clusters sur toutes vos clés principales et des index non clusters sur les clés étrangères (celles que vous utilisez pour faire les jointures).

Je dois noter que ces deux requêtes sont équivalentes si et uniquement si vous avez des valeurs correspondantes dans toutes vos conditions de jointure (c'est-à-dire renvoyer toujours toutes les lignes de la table principale). Sinon, vous obtiendrez null de la sous-requête s'il n'y a pas de match. Les jointures intérieures filtrent activement toutes les lignes qui ne correspondent pas aux conditions de jointure. L'approche de sous-requête est en fait équivalente (dans les résultats, pas la vitesse ou l'exécution) à une jointure extérieure gauche.


4 commentaires

+1. Comme vous le soulignez, les victoires à avoir eu d'indexation réfléchie sont beaucoup plus susceptibles de produire des gains importants. (Mais la vérification du plan d'exécution leur permettra de savoir avec certitude!)


+1 "Vérifiez les plans d'exécution de la requête pour vous-même!" C'est le seul moyen d'être sûr. L'optimiseur pourrait les transformer en jointures pour vous automatiquement. Bien que les deux requêtes ne sont pas exactement les mêmes. # 1 est une jointure gauche, n ° 2 est une jointure interne. Donc, ils vous donneront des plans différents de toute façon.


Ceci est tout à fait trompeur - c'est une idée fausse commune que les sous-soluies sont plus lentes pour la raison pour laquelle vous avez donnée, où, en fait, SQL Server réécrit les sous-requêtes comme jointures dans la mesure du possible pendant la recompilation.


@kragen: Veuillez lire l'intégralité de mon entrée. Spécifiquement, "mais cela est généralement géré par le compilateur" et "vérifier les plans d'exécution de la requête". Voir aussi le commentaire de la plage. Cela a été adressé et n'est pas mal interprété le moins.



0
votes

Les sous-requêtes de manière générale (c'est-à-dire le premier exemple) sont plus lentes, mais le moyen le plus simple d'optimiser et d'analyser vos requêtes les essaie via votre base de données spécifique, MS SQL Server fournit d'excellentes outils d'analyse et de réglage des performances.


1 commentaires

C'est simplement faux - Souvent SQL Server analyser les sous-requêtes dans un arborescence d'exécution identique à celui produit par une jointure.



10
votes

La première méthode n'est pas du tout une jointure intérieure, c'est une sous-requête corrélée. Et ils ressemblent davantage à des jointures extérieures à gauche que les jointures intérieures car elles reviendront nulles quand il n'y a pas de valeur correspondante.


0 commentaires

3
votes

Le premier ressemble à une façon pathologique de faire une jointure à moi. Je l'éviterais, sinon d'autre raison que c'est inhabituel - un DBA SQL expérimenté le regardant pour le maintenir passera un certain temps à la recherche de la raison pour laquelle il est codé comme ça, quand il n'y a pas de vraie raison aussi loin que ce que vous avez veux que la requête fasse. Il se comporte davantage comme une jointure extérieure s'il y a des données manquantes.

Le deuxième exemple semble normal.

Vous devez savoir que la manière de faire de la vieille jointure intérieure est comme ceci: < Pré> xxx

et à une supposition ceci est équivalent à la "join interne" moderne table sur champ sur "une fois analysé.

Comme l'autre réponse indique, si vous recherchez des requêtes plus rapides, la première chose à faire est de vérifier que les indices des tables sont triés. Ensuite, regardez le plan d'exécution de la requête.


1 commentaires

Il semble que cette syntaxe soit ce qu'il est après. Les index ou aucun index effectuant des sous-requêtes pour chaque table de lignes sélectionnée seront lents pour même une petite table (comme plus de 4000 rangées).



0
votes

Beaucoup de programmeurs SQL sont tout à fait incarcérables que l'optimiseur résout fréquemment les sous-soluies dans des jointures. Il n'y a probablement aucune cause de malheurs de performance dans une requête.

Voir le plan d'exécution!


0 commentaires

1
votes

Les deux questions de l'OP disent des choses très différentes et ne produisent que les mêmes résultats si les hypothèses de modèle de données correctes sont en place:

  1. chacune des colonnes utilisées dans la recherche n'a pas de contraintes nuls ni des contraintes de clé étrangère.

  2. La clé principale ou une clé unique de la table de recherche est utilisée.

    Cela peut être dans le cas spécifique à OP, ces hypothèses sont vraies, mais dans le cas général sont différents.

    Comme d'autres l'ont souligné, la sous-requête ressemble davantage à une jointure extérieure en ce sens qu'elle redonnera une nulle pour les colonnes Nom, description et nom de travail au lieu de filtrer la rangée entièrement.

    En outre, si l'une des sous-requêtes retourne plus d'une ligne, vous obtiendrez une erreur.

    En ce qui concerne la préférence personnelle, je préfère le deuxième exemple avec la syntaxe de jointure, mais cela est subjectif.


0 commentaires

0
votes

Je pense que le second est exécuté plus rapidement. La raison derrière cela consiste à utiliser des alias (T, C, M etc. dans votre exemple), le moteur relationnel ne peut facilement connaître le pointeur à l'emplacement de la table.

Je pense que c'est l'un des conseils de SQL Tunning.


0 commentaires

1
votes

En règle générale, il y a aucune différence dans la performance des sous-couches simples vs jointures - il s'agit d'une idée fausse courante que les sous-requêtes sont beaucoup plus lentes (car SQL Server doit boucler dans la requête interne), mais généralement parlant ceci est simplement faux! Pendant le processus de compilation SQL Server produit un arborescence d'exécution, et souvent dans ces sous-candidats d'arbres équivalents à des jointures.

Sa valeur ne pouvant noter que vos deux requêtes ne sont pas logiques et a produit des résultats différents pour moi, la deuxième requête devrait réellement lire quelque chose dans le sens de: (cela n'est toujours pas identique, mais sa plus proche) xxx

dans mes tests la sous-requête produite Un plan d'exécution avec un nombre considérable de lectures (15 par opposition à 1000), mais légèrement plus élevé, la moyenne des temps d'exécution était à peu près équivalente.

sa valeur à noter cependant que cela ne serait pas toujours le cas (en particulier lors de l'évaluation des fonctions à l'intérieur d'une sous-requête), et parfois vous pouvez rencontrer des problèmes en raison d'une sous-requête. En règle générale, il est toutefois de préoccuper de ces cas uniquement lorsque vous rencontrez des problèmes de performance.


0 commentaires