2009-09-09 9 views
21

J'ai une requête relativement simple reliant deux tables. Le critère "Où" peut être exprimé soit dans les critères de jointure, soit dans une clause where. Je me demande lequel est le plus efficace.Critères de filtre SQL dans les critères de jointure ou clause where plus efficace

La requête consiste à trouver les ventes maximales pour un vendeur depuis le début jusqu'à leur promotion.

Case 1

select salesman.salesmanid, max(sales.quantity) 
from salesman 
inner join sales on salesman.salesmanid =sales.salesmanid 
        and sales.salesdate < salesman.promotiondate 
group by salesman.salesmanid 

Case 2

select salesman.salesmanid, max(sales.quantity) 
from salesman 
inner join sales on salesman.salesmanid =sales.salesmanid 
where sales.salesdate < salesman.promotiondate 
group by salesman.salesmanid 

Remarque Cas 1 manque une clause where tout à fait

SGBDR est Sql Server 2005

EDIT Si la seconde morceau de le critère de jointure ou la clause where était sales.salesdate < une date fixe, donc ce n'est pas vraiment un critère de jonction des deux tables qui change la réponse.

+0

Qu'y a-t-il de mal à tester le temps que prennent ces requêtes? – ChristopheD

+2

Parce que la requête est mise en cache mais merci, vraiment – Gratzy

+1

@Gratzy - DBCC FREEPROCCACHE http://msdn.microsoft.com/en-us/library/ms174283.aspx –

Répondre

20

Je n'utiliserais pas la performance comme facteur décisif ici - et honnêtement, je ne pense pas qu'il y ait une différence de performance mesurable entre ces deux cas, vraiment.

J'utiliserais toujours le cas # 2 - pourquoi? Parce qu'à mon avis, vous devriez seulement mettre les critères réels qui établissent le JOIN entre les deux tables dans la clause JOIN - tout le reste appartient à la clause WHERE.

Juste une question de garder les choses propres et de mettre les choses où elles appartiennent, IMO.

Évidemment, il y a des cas avec LEFT OUTER JOINs où le placement des critères fait une différence quant aux résultats obtenus - ces cas seraient évidemment exclus de ma recommandation.

Marc

+1

+1 - bonne réponse marc –

+0

On pourrait argumenter que le cas n ° 1 est meilleur pour l'encapsulation (dans ce cas, la clause WHERE est seulement utilisée pour les critères de la table principale). –

0

Cela peut sembler désinvolte, mais la réponse est quelle que soit la requête pour laquelle l'analyseur de requête produit le plan le plus efficace. À mon avis, ils semblent être équivalents, donc l'analyseur de requêtes peut très bien produire des plans identiques, mais vous devrez tester.

0

Ni est plus efficace, en utilisant la méthode WHERE est considérée comme l'ancienne façon de le faire (http://msdn.microsoft.com/en-us/library/ms190014.aspx). Vous pouvez regarder le plan d'exécution et voir qu'ils font la même chose.

+0

Mon exemple n'était pas le meilleur changement la deuxième partie de la jointure et ou where clause pour être une date fixe au lieu d'une date dans la table de vendeur. – Gratzy

+0

Ahh d'accord, bien dans les deux cas, le plan d'exécution est votre ami. Analysez-le pour trouver celui qui a les meilleures performances. Mon pari est qu'ils seront identiques. –

1

Je ne pense pas que vous trouverez une réponse définitive pour celle qui s'applique à tous les cas. Les 2 ne sont pas toujours interchangeables - puisque pour certaines requêtes (quelques jointures à gauche) vous obtiendrez des résultats différents en plaçant les critères dans la ligne WHERE vs FROM.

Dans votre cas, vous devez évaluer ces deux requêtes. Dans SSMS, vous pouvez afficher les plans d'exécution estimés et réels de ces deux requêtes - ce serait une bonne première étape pour déterminer lequel est le plus optimal. Vous pouvez également afficher l'heure & IO pour chaque (définir l'heure de la statistique sur, définir les statistiques sur) - et cela vous donnera également des informations pour prendre votre décision.Dans le cas des questions dans votre question - je parierais qu'ils vont tous les deux sortir avec le même plan de requête - donc dans ce cas, cela peut ne pas importer, mais dans d'autres, il pourrait potentiellement produire des plans différents.

Essayez ceci pour voir la différence entre les deux ...

SET STATISTICS IO ON 
SET STATISTICS TIME ON 

select salesman.salesmanid, 
     max(sales.quantity) 
from salesmaninner join sales on salesman.salesmanid =sales.salesmanid 
     and sales.salesdate < salesman.promotiondate 
group by salesman.salesmanid 

select salesman.salesmanid, 
     max(sales.quantity) 
from salesmaninner join sales on salesman.salesmanid = sales.salesmanid 
where sales.salesdate < salesman.promotiondate 
group by salesman.salesmanid 

SET STATISTICS TIME OFF 
SET STATISTICS IO OFF 
+0

Ce serait spécifiquement des jointures internes – Gratzy

+1

Gratzy - dans ce cas, je suis d'accord avec marc_s - les critères de filtrage devraient être conservés dans la partie WHERE de la requête, et les critères de jointure devraient être conservés dans la partie FROM de la requête. –

+0

Est-il important que la table de critères where ait beaucoup plus de lignes. Je sais que cela peut sembler anodin mais je me demandais s'il serait alors préférable de faire partie des critères de jointure au lieu de la clause where – Gratzy

0

Se familiariser avec le plan d'exécution estimé dans SQL Management Studio !! Comme d'autres l'ont dit, vous êtes à la merci de l'analyseur, peu importe ce que vous faites, alors faites confiance à ses estimations. Je suppose que les deux que vous avez fournis produiraient exactement le même plan.

S'il s'agit d'une tentative de changer une culture de développement, choisissez celui qui vous donne un meilleur plan; Pour ceux qui sont identiques, suivez la culture

Je l'ai commenté sur d'autres publications "efficacité" comme celle-ci (elle est à la fois sincère et sarcastique) - si c'est là que résident vos goulets d'étranglement, puis high-five à toi et ton équipe.

+1

Oui, je connais le plan d'exécution estimé. Cependant, il ne me dira pas pourquoi il génère le plan d'exécution comme il le fait. Je cherchais à comprendre pourquoi on pourrait être plus efficace que l'autre. – Gratzy

+0

@Gratzy: http://www.amazon.com/Gurus-Guide-Server-Architecture-Internals/dp/0201700476 –

3

Je préfère avoir des critères codés en dur dans la jointure. Cela rend le SQL beaucoup plus lisible et portable.

Lisibilité: Vous pouvez voir exactement quelles données vous allez obtenir car tous les critères de la table sont écrits directement dans la jointure. Dans les grandes déclarations, les critères peuvent être enterrés dans 50 autres expressions et peuvent facilement être manqués. Portabilité: Vous pouvez simplement copier un fragment de la clause FROM et le coller ailleurs. Cela donne les jointures et tous les critères dont vous avez besoin pour l'accompagner. Si vous utilisez toujours ce critère lorsque vous joignez ces deux tables, il est plus logique de le placer dans la jointure.

Par exemple:

FROM 
table1 t1 
JOIN table2 t2_ABC ON 
    t1.c1 = t2_ABC.c1 AND 
    t2_ABC.c2 = 'ABC' 

Si vous avez besoin d'obtenir une deuxième colonne de tableau 2 vous suffit de copier ce bloc dans le Bloc-notes, la recherche/repalce « ABC » et presto et tout le nouveau bloc de code prêt à remettez en place.

Supplémentaire: Il est également plus facile de passer d'une jointure interne à une jointure externe sans avoir à se soucier des critères qui peuvent circuler dans la clause WHERE.

Je réserve la clause WHERE strictement pour les critères d'exécution lorsque cela est possible. En ce qui concerne l'efficacité: Si vous parlez de la vitesse d'exécution, alors comme tout le monde l'a dit, c'est redondant. Si vous parlez de faciliter le débogage et la réutilisation, alors je préfère l'option 1.

+0

En résumé, les critères dans le JOIN sont meilleurs pour l'encapsulation, et l'encapsulation accrue est généralement meilleure. –

1

Une chose que je veux dire enfin que j'ai notifié, avant cela .. Les deux façons peuvent donner la même performance ou en utilisant les critères à Où la clause peut être un peu plus rapide que celle trouvée dans certaines réponses.

Mais j'identifié une différence, vous pouvez utiliser pour vos besoins logiques ..

  1. En utilisant les critères à ON clause ne filtrent pas/sauter les lignes pour sélectionner les colonnes de jointure au lieu seraient nulles sur la base des conditions

  2. en utilisant les critères à clause peut filtrer/sauter les lignes à l'ensemble des résultats

0

Le cas 1 (critère dans JOIN) est meilleur pour l'encapsulation, et l'encapsulation accrue est généralement une bonne chose: réduction des omissions de copier/coller dans une autre requête, réduction des bogues si converti en LEFT JOIN et meilleure lisibilité et moins de "bruit" dans la clause WHERE). Dans ce cas, la clause WHERE capture uniquement les critères de table principaux ou les critères qui s'étendent sur plusieurs tables.

Questions connexes