Une jointure est-elle optimisée pour une clause where lors de l'exécution?


14

Quand j'écris une requête comme celle-ci ...

select *
from table1 t1
join table2 t2
on t1.id = t2.id

L'optimiseur SQL, pas sûr que ce soit le bon terme, traduit-il cela en ...

select *
from table1 t1, table2 t2
where t1.id = t2.id

Essentiellement, l'instruction Join dans SQL Server est-elle simplement un moyen plus simple d'écrire SQL? Ou est-il réellement utilisé au moment de l'exécution?

Edit: j'utilise presque toujours et j'utiliserai presque toujours la syntaxe Join. Je suis juste curieux de savoir ce qui se passe.


1
Pourriez-vous développer le "presque"? Quand utiliseriez-vous la syntaxe à l'ancienne et pourquoi?
Aaron Bertrand

2
Un cas de bord où cela fait une différence est si vous ajoutez un (obsolète) GROUP BY ALLdans
Martin Smith

@MartinSmith quelqu'un utilise- GROUP BY ALLt-il exprès? :-)
Aaron Bertrand

@AaronBertrand - J'en doute! Ne pensez pas que j'aie jamais vu quelqu'un l'utiliser.
Martin Smith

Réponses:


20

Celles-ci s'effondrent à la même chose en interne. Le premier est celui que vous devez toujours écrire . Plus important encore, pourquoi est-ce important? Ils sont identiques en termes de plan d'exécution et de performances (en supposant que vous ne vous trompez pas, ce qui est plus facile à faire avec la syntaxe paresseuse à l'ancienne).

Voici la preuve en utilisant AdventureWorks qu'il n'y en a pas CROSS JOINet filtercontinue.


La jointure explicite:

entrez la description de l'image ici


La jointure implicite:

entrez la description de l'image ici


Regardez, ma! Plans identiques, résultats identiques, aucune jointure croisée ou filtre vu nulle part.

(Pour plus de clarté, l'avertissement sur l' SELECTopérateur dans les deux cas est une conversion implicite affectant la cardinalité, rien à voir avec la jointure dans les deux cas.)


20

À strictement parler, il existe une différence dans l'entrée de l'optimiseur de requête entre les deux formes:

-- Input tree (ISO-89)
SELECT
    p.Name,
    Total = SUM(inv.Quantity)
FROM 
    Production.Product AS p,
    Production.ProductInventory AS inv
WHERE
    inv.ProductID = p.ProductID
GROUP BY
    p.Name
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);

Arborescence d'entrée ISO-89

-- Input tree (ISO-92)
SELECT
    p.Name,
    Total = SUM(inv.Quantity)
FROM Production.Product AS p
JOIN Production.ProductInventory AS inv ON
    inv.ProductID = p.ProductID
GROUP BY
    p.Name
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);

Arborescence d'entrée ISO-92

Comme vous pouvez le voir, le ONprédicat de la clause est étroitement lié à la jointure en utilisant la syntaxe moderne. Avec l'ancienne syntaxe, il existe une jointure croisée logique suivie d'une sélection relationnelle (un filtre de ligne).

L'optimiseur de requêtes réduit presque toujours la sélection relationnelle dans la jointure pendant l'optimisation, ce qui signifie que les deux formulaires produiront très probablement des plans de requête équivalents, mais il n'y a aucune garantie réelle.


4

Pour la jointure interne, ils sont interchangeables, mais pour les jointures externes, ils ont des significations différentes - ON correspond et WHERE est un filtrage simple. Il est donc préférable de s'en tenir à la correspondance de syntaxe JOIN correcte sur ON.


4

OK, j'étais curieux alors j'ai fait un test. J'ai obtenu des plans d'exécution réels pour les éléments suivants.

select * 
from sys.database_principals prin, sys.database_permissions perm
WHERE prin.principal_id = perm.grantee_principal_id

et

select * 
from sys.database_principals prin
JOIN sys.database_permissions perm
    ON prin.principal_id = perm.grantee_principal_id

Je les ai comparés objet par objet et ils étaient identiques. Donc, au moins pour un exemple très simple, ils sont arrivés à la même chose. J'ai également vérifié les statistiques IO et le temps et ils étaient suffisamment proches pour être la même chose.

Cela étant dit, vous devez utiliser la JOINsyntaxe car elle est plus facile à lire et vous êtes moins susceptible de faire des erreurs, en particulier dans les requêtes complexes. Et la syntaxe *=/ =*pour les OUTERjointures a déjà été supprimée à partir de SQL-Server 2005.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.