Uma associação é otimizada para uma cláusula where em tempo de execução?


14

Quando escrevo uma consulta como esta ...

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

O otimizador de SQL, que não tem certeza se esse é o termo correto, traduz isso para ...

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

Essencialmente, a instrução Join no SQL Server é apenas uma maneira mais fácil de escrever sql? Ou é realmente usado em tempo de execução?

Edit: Eu quase sempre, e quase sempre, uso a sintaxe Join. Estou apenas curioso para saber o que acontece.


1
Você poderia elaborar sobre o "quase"? Quando você usaria a sintaxe antiga e por quê?
Aaron Bertrand

2
Um caso extremo em que faz a diferença é se você adicionar um (obsoleto) GROUP BY ALLem
Martin Smith

@MartinSmith alguém usa GROUP BY ALLde propósito? :-)
Aaron Bertrand

@AaronBertrand - duvido! Não pense que eu já vi alguém usá-lo.
Martin Smith

Respostas:


20

Aqueles colapsam internamente à mesma coisa. O primeiro é o que você deve sempre escrever . Mais importante, por que isso importa? Eles são idênticos em termos de plano de execução e desempenho (supondo que você não estrague tudo, o que é mais fácil de fazer com a sintaxe preguiçosa e antiga).

Aqui está uma prova, usando o AdventureWorks, de que não existe CROSS JOINe está filteracontecendo.


A junção explícita:

insira a descrição da imagem aqui


A junção implícita:

insira a descrição da imagem aqui


Olha ma! Planos idênticos, resultados idênticos, sem junções cruzadas ou filtros vistos em qualquer lugar.

(Para maior clareza, o aviso no SELECToperador nos dois casos é uma conversão implícita que afeta a cardinalidade, nada a ver com a junção nos dois casos.)


20

A rigor, há uma diferença na entrada do otimizador de consulta entre os dois formulários:

-- 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);

Árvore de entrada 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);

Árvore de entrada ISO-92

Como você pode ver, o ONpredicado da cláusula está fortemente vinculado à junção usando a sintaxe moderna. Com a sintaxe mais antiga, há uma junção cruzada lógica seguida por uma seleção relacional (um filtro de linha).

O otimizador de consulta quase sempre recolhe a seleção relacional na junção durante a otimização, o que significa que os dois formulários provavelmente produzirão planos de consulta equivalentes, mas não há garantia real.


4

Para junção interna, eles são intercambiáveis, mas para Junções externas, eles têm significados diferentes - o ON está correspondendo e WHERE é uma filtragem simples. Portanto, é melhor manter a correspondência de sintaxe JOIN correta no ON.


4

OK, fiquei curioso, então fiz um teste. Eu tenho planos de execução reais para o seguinte.

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

e

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

Comparei-os objeto por objeto e eles eram idênticos. Então, pelo menos para um exemplo muito simples, eles saíram para a mesma coisa. Também verifiquei as estatísticas IO e o tempo, e eles estavam perto o suficiente para serem a mesma coisa.

Dito isto, você deve usar a JOINsintaxe porque é mais fácil de ler e é menos provável que cometa erros, principalmente em consultas complicadas. E a sintaxe *=/ =*para OUTERjunções já foi removida a partir do SQL-Server 2005.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.