41 votes

WHERE Clause vs ON lors de l'utilisation de JOIN

En supposant que j'ai le code T-SQL suivant:

 SELECT * FROM Foo f
INNER JOIN Bar b ON b.BarId = f.BarId;
WHERE b.IsApproved = 1;
 

Le suivant renvoie également le même ensemble de lignes:

 SELECT * FROM Foo f
INNER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId);
 

Ce n'est peut-être pas le meilleur exemple de cas ici, mais existe-t-il une différence de performance entre ces deux?

43voto

StuartLC Points 35534

Faites juste attention de la différence avec les jointures externes

SELECT * 
FROM Foo f 
LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId); 

N'est pas le même que

SELECT * 
FROM Foo f 
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE b.IsApproved = 1; 

Depuis pour "échoué" jointures externes sur la Barre, b.IsApproved sera toujours NULL et, partant, de les filtrer.

Une autre façon de voir c'est que pour l' LEFT OUTER JOIN Bar b ON (b.IsApproved = 1) AND (b.BarId = f.BarId), que le filtre additionnel (b.IsApproved = 1) sera ignoré si la jointure (b.BarId = f.BarId) échoue, car le LEFT/RIGHT OUTER JOIN garantit la GAUCHE / DROITE des lignes de la table seront conservés même si la jointure échoue.

Mise à jour: Pour répondre à la question posée par Conrad, l'équivalent de la LOJ pour un filtre OPTIONNEL serait:

SELECT * 
FROM Foo f 
LEFT OUTER JOIN Bar b ON (b.BarId = f.BarId)
WHERE 
(b.IsApproved IS NULL OR b.IsApproved = 1);

c'est à dire OÙ La clause doit considérer à la fois la condition si la jointure échoue (NULL) et le filtre doit être ignoré, et où la jointure réussit et que le filtre doit être appliqué. (b.IsApproved ou b.BarId a pu être testé pour les NULS)

30voto

aF. Points 15815

Non, l'optimiseur de requête est suffisamment intelligent pour choisir le même plan d'exécution pour les deux exemples.

Vous pouvez utiliser SHOWPLAN pour vérifier le plan d'exécution.

6voto

Landin Martens Points 792
 SELECT * FROM Foo f
INNER JOIN Bar b ON b.BarId = f.BarId
WHERE b.IsApproved = 1;
 

C'est la meilleure forme pour y aller. Il est facile à lire et à modifier. Dans le monde des affaires, c'est ce que vous voudriez faire. En ce qui concerne les performances, elles sont identiques.

0voto

Fabricio Araujo Points 2687

J'ai eu quelques cas où l'optimiseur n'était pas assez intelligent, même sur les versions récentes de MSSQL - et la différence de performances était énorme.

Mais il s’agit d’une exception. La plupart du temps, l’optimiseur SQL Server résoudra le problème et obtiendra le bon plan.

Donc, maintenez la politique d’utilisation des filtres sur la clause WHERE et optimisez-le si nécessaire.

0voto

Jason L Points 23

Je viens de lancer un test de requête sur quatre tables - une table principale avec trois INNER JOINs et un total de quatre paramètres, et comparé les plans d’exécution des deux approches (en utilisant les critères de filtrage dans ON du JOIN, puis dans la clause WHERE).

Les plans d'exécution sont exactement les mêmes. J'ai exécuté ceci sur SQL Server 2008 R2.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X