Eu tenho duas mesas
@T1 TABLE
(
Id INT,
Date DATETIME
)
@T2 TABLE
(
Id INT,
Date DATETIME
)
Essas tabelas têm um índice não agrupado em (Id, Data)
E eu entro nessas tabelas
SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON
t1.Id = t2.Id
WHERE
t1.Date <= GETDATE()
AND
t2.Date <= GETDATE()
Isso também pode ser escrito como
SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON
t1.Id = t2.Id
AND
t1.Date <= GETDATE()
AND
t2.Date <= GETDATE()
Minha pergunta é: qual dessas duas consultas oferece o melhor desempenho e por quê? Ou eles são iguais?
Respostas:
O desempenho será o mesmo. O otimizador reconhecerá isso e criará o mesmo plano.
Por outro lado, não diria que são iguais. A primeira forma da pergunta é muito mais legível e geralmente esperada.
Por exemplo, usando algumas tabelas que tenho em mãos, você pode ver que o plano de execução é exatamente o mesmo, independentemente de como escrevo a consulta.
Você deve poder determinar os planos de consulta para suas próprias tabelas e conjunto de dados, para poder ver o que acontece na sua situação.
Dá esses planos de execução
fonte
INNER JOIN
. Se você jogar umOUTER JOIN
, então eles decididamente não são os mesmos.Eles são semanticamente idênticos e o otimizador não deve ter problemas para reconhecer esse fato e gerar planos idênticos.
Eu costumo colocar condições referenciando as duas tabelas no
ON
e condições referenciando apenas uma tabela noWHERE
.Para
OUTER JOINS
mover, as condições podem afetar a semântica, no entanto.fonte
Em casos simples, será o mesmo. No entanto, vi consultas muito complexas com várias associações terem planos significativamente diferentes. Uma recente na qual eu estava trabalhando começou com uma tabela que possui cerca de 6 milhões de linhas associadas a cerca de 20 tabelas diferentes. Somente a primeira junção a esta tabela foi uma junção interna ; todas as outras ficaram juntas externas. O filtro na cláusula where foi parametrizado da seguinte forma:
Esse filtro foi usado posteriormente no plano, em vez de anteriormente. Quando mudei essas condições para a primeira junção interna, o plano mudou drasticamente quando o filtro foi aplicado no início do plano para limitar o conjunto de resultados e minha CPU e o tempo decorrido caíram aproximadamente 310%. Portanto, como em muitas perguntas do SQL Server, isso depende.
fonte
Em geral, onde você coloca os filtros faz a diferença.
Embora Tom V diga que o Otimizador reconhecerá que as consultas são iguais e criará o mesmo plano, isso nem sempre é verdade. Depende da versão do SQL, da complexidade da sua consulta e da importância para o lote geral que o Optimizer determina.
O Otimizador pode decidir que essa parte do lote não vale a pena gastar tempo suficiente para permitir que ele elabore o melhor plano. Em geral, você obterá melhor desempenho se colocar condições que reduzam a quantidade de dados na qual a consulta precisará trabalhar na cláusula ON, em vez da cláusula WHERE (se possível, pois fazer isso com uma junção externa resultará em um produto cartesiano .)
É um pouco mais fácil para o ocasional desenvolvedor SQL detectar filtros na cláusula WHERE, mas eu trabalhei em algumas tabelas grandes nas quais os filtros na cláusula ON eliminam horas do tempo de execução.
Portanto, se a cláusula tiver o potencial de reduzir drasticamente o número de linhas que a consulta lerá, sempre a colocarei na cláusula ON para ajudar o Optimizer a escolher o melhor plano.
fonte
Sob circunstâncias normais, as condições do filtro podem ser especificadas nas cláusulas WHERE ou JOIN. Eu costumo colocar filtros em WHERE, a menos que a precedência OUTER JOIN possa ser afetada (veja abaixo) ou se o filtro for muito específico para essa tabela (por exemplo, TYPE = 12 para especificar um subconjunto específico de linhas na tabela).
Por outro lado, as cláusulas ON e WHERE podem ser usadas para especificar condições de junção (em oposição às condições de filtro). Enquanto você estiver usando apenas junções INNER, ainda não importa qual você usará em circunstâncias comuns.
Se você estiver usando junções OUTER, no entanto, isso pode fazer muita diferença. Se, por exemplo, você especificar um OUTER JOIN entre duas tabelas (t1 e t2), mas, na cláusula WHERE, especifique um relacionamento eqijoin entre as tabelas (por exemplo, t1.col = t2.col), você acabou de converteu a associação OUTER em uma associação INNER! Isso ocorre porque WHERE pode ser usado para especificar um equijoin (ou talvez uma junção OUTER, dependendo da versão, usando a sintaxe * = obsoleta) sem usar uma cláusula ON, e quando WHERE indica um equijoin interno entre as tabelas, ele substitui um OUTER JOIN (se presente).
A pergunta original era sobre filtros, onde o tipo de junção geralmente não deveria ser um problema, mas uma junção também pode atuar como um filtro e, nessas situações, o posicionamento da condição de junção certamente pode ser importante.
fonte
Com INNER JOINs, é uma questão de estilo.
No entanto, torna-se muito mais interessante com OUTER JOINs. Você deve explorar as diferenças entre consultas com OUTER JOINs e condições na cláusula ON e na cláusula WHERE. O conjunto de resultados nem sempre é o mesmo. É, por exemplo,
o mesmo que
fonte