j'ai deux tables
@T1 TABLE
(
Id INT,
Date DATETIME
)
@T2 TABLE
(
Id INT,
Date DATETIME
)
Ces tables ont un index non clusterisé le (Id, Date)
Et je rejoins ces tables
SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON
t1.Id = t2.Id
WHERE
t1.Date <= GETDATE()
AND
t2.Date <= GETDATE()
Cela peut également s'écrire
SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON
t1.Id = t2.Id
AND
t1.Date <= GETDATE()
AND
t2.Date <= GETDATE()
Ma question est, laquelle de ces deux requêtes donne les meilleures performances et pourquoi? Ou sont-ils égaux?
Réponses:
La performance sera la même. L'optimiseur reconnaîtra cela et créera le même plan.
D'un autre côté, je ne dirais pas qu'ils sont égaux. La première forme de la question est beaucoup plus lisible et généralement attendue.
Pour un exemple utilisant certaines tables que j'ai sous la main, vous pouvez voir que le plan d'exécution est exactement le même, peu importe comment j'écris la requête.
Vous devriez être en mesure de déterminer les plans de requête pour vos propres tables et ensembles de données afin de pouvoir voir ce qui se passe dans votre situation.
Donne ces plans d'exécution
la source
INNER JOIN
. Si vous ajoutez un,OUTER JOIN
ils ne sont décidément pas les mêmes.Ils sont sémantiquement identiques et l'optimiseur ne devrait avoir aucun mal à reconnaître ce fait et à générer des plans identiques.
J'ai tendance à mettre des conditions faisant référence aux deux tables dans le
ON
et des conditions faisant référence à une seule table dans leWHERE
.Pour le
OUTER JOINS
déplacement, les conditions peuvent cependant affecter la sémantique.la source
Dans les cas simples, ce sera la même chose. Cependant, j'ai vu des requêtes très complexes avec plusieurs jointures avoir des plans très différents. Une récente sur laquelle je travaillais a commencé avec une table qui a près de 6 millions de lignes jointes à environ 20 tables différentes. Seule la première jointure de cette table était une jointure interne , toutes les autres restaient des jointures externes. Le filtre dans la clause where a été paramétré quelque chose comme ceci:
Ce filtre a été utilisé plus tard dans le plan plutôt qu'avant. Lorsque j'ai déplacé ces conditions vers la première jointure interne, le plan a radicalement changé car le filtre a été appliqué au début du plan pour limiter le jeu de résultats et mon processeur et le temps écoulé ont chuté d'environ 310%. Ainsi, comme pour de nombreuses questions SQL Server, cela dépend.
la source
En général, l'endroit où vous placez les filtres fait une différence.
Bien que Tom V indique que l'Optimizer reconnaîtra que les requêtes sont les mêmes et proposent le même plan, ce n'est pas toujours vrai. Cela dépend de la version de SQL que vous utilisez, de la complexité de votre requête et de l'importance du lot global que l'Optimizer détermine.
L'optimiseur peut décider que cette partie du lot ne vaut pas la peine de passer suffisamment de temps pour lui permettre d'élaborer le meilleur plan. En général, vous obtiendrez de meilleures performances si vous mettez des conditions qui réduisent la quantité de données sur lesquelles la requête devra travailler dans la clause ON au lieu de la clause WHERE (si possible, car le faire avec une jointure externe se traduira par un produit cartésien .)
Il est un peu plus facile pour le développeur SQL occasionnel de repérer les filtres dans la clause WHERE, mais j'ai travaillé sur de grandes tables où le fait d'avoir les filtres dans la clause ON réduit les heures de fonctionnement.
Donc, si la clause a le potentiel de réduire considérablement le nombre de lignes que la requête lira, je la mettrai toujours dans la clause ON pour aider l'Optimizer à choisir le meilleur plan.
la source
Dans des circonstances ordinaires, les conditions de filtrage peuvent être spécifiées dans les clauses WHERE ou JOIN. J'ai tendance à placer des filtres sous WHERE à moins que la priorité OUTER JOIN ne soit affectée (voir ci-dessous) ou si le filtre est très spécifique à cette table (par exemple TYPE = 12 pour spécifier un sous-ensemble spécifique de lignes dans la table).
D'un autre côté, les clauses ON et WHERE peuvent être utilisées pour spécifier des conditions de jointure (par opposition aux conditions de filtrage). Tant que vous n'utilisez que des jointures INNER, peu importe ce que vous utilisez dans des circonstances ordinaires.
Cependant, si vous utilisez des jointures externes, cela peut faire une grande différence. Si, par exemple, vous spécifiez un OUTER JOIN entre deux tables (t1 et t2) mais que, dans la clause WHERE, continuez à spécifier une relation eqijoin entre les tables (par exemple t1.col = t2.col), vous avez juste converti la jointure OUTER en jointure INNER! En effet, WHERE peut être utilisé pour spécifier une équijoin (ou peut-être même une jointure OUTER, selon la version, en utilisant la syntaxe obsolète * =) sans utiliser de clause ON, et lorsque WHERE indique une équijoin interne entre les tables, elle remplace une OUTER REJOIGNEZ (le cas échéant).
La question initiale concernait les filtres, où le type de jointure ne devrait souvent pas être un problème, mais une jointure peut également agir comme un filtre et dans ces situations, le placement de la condition de jointure peut certainement avoir de l'importance.
la source
Avec INNER JOINs, c'est un problème de style.
Cependant, cela devient beaucoup plus intéressant avec OUTER JOINs. Vous devez explorer les différences entre les requêtes avec OUTER JOIN et les conditions dans la clause ON et la clause WHERE. L'ensemble de résultats n'est pas toujours le même. Est, par exemple,
le même que
la source