Junção interna vs Onde

257

Existe uma diferença no desempenho (no oracle) entre

Select * from Table1 T1 
Inner Join Table2 T2 On T1.ID = T2.ID

E

Select * from Table1 T1, Table2 T2 
Where T1.ID = T2.ID

?

juan
fonte
1
apenas para o registro, as consultas que tenho visto retornar resultados diferentes somente mudando de uma junção de uma cláusula where
BlackTigerX
12
@BlackTigerX: Resultados diferentes? Havia alguma junção externa envolvida? Porque não vejo como resultados diferentes ocorreriam entre um inner join ... oncritério de junção equivalente e versus colocar na wherecláusula.
Shannon Severance
na versão antiga do banco de dados Oracle não existejoin
MajidTaheri
2
@MajidTaheri: de quantos anos você está falando de uma versão do Oracle? Qualquer versão suportada pelo Oracle suporta a notação JOIN.
precisa saber é o seguinte
Procure respostas gerais ou práticas recomendadas baseadas em casos triviais. Gostaria de ver uma "correspondência" com cláusulas where mais complexas que envolvem várias condições AND. Pelo menos com o SQL Server, há um ponto de cruzamento.
crokusek

Respostas:

195

Não! O mesmo plano de execução, observe estas duas tabelas:

CREATE TABLE table1 (
  id INT,
  name VARCHAR(20)
);

CREATE TABLE table2 (
  id INT,
  name VARCHAR(20)
);

O plano de execução para a consulta usando a junção interna:

-- with inner join

EXPLAIN PLAN FOR
SELECT * FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

E o plano de execução da consulta usando uma cláusula WHERE.

-- with where clause

EXPLAIN PLAN FOR
SELECT * FROM table1 t1, table2 t2
WHERE t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2
kiewic
fonte
4
Eu realmente gostaria de ver se há alguma documentação oficial da Oracle dizendo sobre isso.
4 Leave Cover
68

Se o otimizador de consultas estiver fazendo seu trabalho corretamente, não deverá haver diferença entre essas consultas. São apenas duas maneiras de especificar o mesmo resultado desejado.

Craig Trader
fonte
22
Sim, o desempenho deve ser o mesmo. Mas a sintaxe SELECT * FROM Tabela1, Tabela2 ONDE ... é MAU!
Joel Coehoorn
2
Acho muito mais fácil compreender FOR INNER JOINS do que a sintaxe SQL-92. Sua milhagem pode variar.
Craig Trader
25
Acho a sintaxe WHERE mais fácil de ler do que INNER JION - acho que é como o Vegemite. A maioria das pessoas no mundo provavelmente acha isso nojento, mas as crianças criadas comê-lo adoram.
27468 ScottCher
3
Vegemite é realmente desagradável, mas, novamente, eu amo sucata. Vai saber.
StingyJack 27/08
2
@ Darryl Eu acho que os JOINsão mais fáceis de ler, porque a condição para ingressar nas tabelas é definida imediatamente, imediatamente em vez de "em algum lugar" da WHEREcláusula. Prefiro reservar a WHEREcláusula para limitar o conjunto de dados (por exemplo WHERE DATE > (SYSDATE - 1)) em vez de também definir como as tabelas se relacionam (por exemplo WHERE T1.ID = T2.ID). Para uma tabela pequena como o exemplo em questão faz pouca diferença, mas para consultas grandes envolvendo várias tabelas e várias condições, acho que torna a consulta muito mais fácil de entender.
ImaginaryHuman072889
61

Eles devem ser exatamente iguais. No entanto, como uma prática de codificação, eu preferiria ver o Join. Articula claramente sua intenção,

Nescio
fonte
8
Concordo. Especialmente se você estiver ingressando em várias tabelas, é muito mais fácil analisar uma instrução select se estiver fazendo junções explícitas.
1913 Paul Morie
13
De fato. As junções representam um relacionamento semântico entre dois conjuntos de dados, mas um where sugere um conjunto filtrado. +1
EightyOne Unite
26

Usando JOIN facilita a leitura do código, pois é auto-explicativo.

Não há diferença de velocidade ( acabei de testá-lo ) e o plano de execução é o mesmo.

user21241
fonte
Obrigado. Eu estava procurando por compressão de velocidade entre esses dois métodos.
Farhad Navayazdan
14

Não sei sobre o Oracle, mas sei que a sintaxe antiga está sendo preterida no SQL Server e desaparecerá eventualmente. Antes de usar essa sintaxe antiga em uma nova consulta, verifiquei o que a Oracle planeja fazer com ela.

Eu prefiro a sintaxe mais recente do que a mistura dos critérios de junção com outras condições onde necessárias. Na sintaxe mais recente, é muito mais claro o que cria a junção e quais outras condições estão sendo aplicadas. Não é realmente um grande problema em uma consulta curta como essa, mas fica muito mais confuso quando você tem uma consulta mais complexa. Como as pessoas aprendem sobre as consultas básicas, eu tenderia a preferir que as pessoas aprendessem a usar a sintaxe de junção antes que precisassem em uma consulta complexa.

E, novamente, eu não conheço a Oracle especificamente, mas sei que a versão do SQL Server da junção esquerda de estilo antigo é falha até no SQL Server 2000 e fornece resultados inconsistentes (às vezes uma junção esquerda às vezes uma junção cruzada), portanto nunca deve ser usava. Esperamos que a Oracle não sofra o mesmo problema, mas certamente as junções esquerda e direita podem ser muito mais difíceis de expressar adequadamente na sintaxe antiga.

Além disso, tem sido minha experiência (e é claro que essa é estritamente uma opinião pessoal, você pode ter uma experiência diferente) de que os desenvolvedores que usam as junções padrão ANSII tendem a entender melhor o que é uma junção e o que isso significa em termos de obter dados fora do banco de dados. Acredito que isso aconteça porque a maioria das pessoas com bom entendimento do banco de dados tende a escrever consultas mais complexas e essas me parecem muito mais fáceis de manter usando o ANSII Standard do que o estilo antigo.

HLGEM
fonte
1
Amém irmão. Abaixo os JOINERS !!
27468 ScottCher
14

[Para um ponto de bônus ...]

O uso da sintaxe JOIN permite comentar mais facilmente a junção, pois tudo está incluído em uma linha. Isso pode ser útil se você estiver depurando uma consulta complexa

Como todo mundo diz, eles são funcionalmente iguais, no entanto, o JOIN é mais claro de uma declaração de intenções. Portanto, ele pode ajudar o otimizador de consultas nas versões atuais do Oracle em certos casos (não faço ideia se existe), pode ajudar o otimizador de consultas em versões futuras do Oracle (ninguém tem idéia) ou pode ajudar se você altera o fornecedor do banco de dados.

Chris Gill
fonte
2
Ou ... altere facilmente INNER JOINS para LEFT JOINS, para ver qual junção está causando a perda das linhas esperadas. Faço isso porque faço toda a consulta de uma só vez. Se você comentar INNER JOINS, precisará fazer um processo de eliminação. Leva mais tempo. Mas +1 para você, porque esse é um dos meus motivos favoritos para INNER JOINS, além da legibilidade!
Matthew McPeak
13

Eles são logicamente idênticos, mas nas versões anteriores do Oracle que adotavam a sintaxe ANSI, muitas vezes havia bugs em casos mais complexos, portanto, às vezes, você encontra resistência dos desenvolvedores da Oracle ao usá-lo.

David Aldridge
fonte
Versões anteriores do Oracle tinham erros com isso? Quão cedo? Quais versões?
27968 ScottCher
O Metalink tem detalhes ... eles aparecem por todo o lugar.
David Aldridge
7

O desempenho deve ser idêntico, mas eu sugeriria o uso da versão de junção devido à maior clareza quando se trata de junções externas.

Também produtos cartesianos não intencionais podem ser evitados usando a versão de junção.

Um terceiro efeito é um SQL mais fácil de ler com uma condição WHERE mais simples.

stili
fonte
Eu realmente acho que a chave são os efeitos não intencionais, onde o critério é ambíguo. Se você especificar o tipo de associação, saberá exatamente o que está recebendo. Descobri que bancos de dados diferentes e até versões diferentes da mesma plataforma de banco de dados manipularão valores nulos de maneira diferente em uma associação implícita. Quando você especifica esquerda / direita interna / externa, passa o tempo pensando sobre qual é a correta. Quando você usa o método ambíguo, assume que ele funciona da maneira que você espera / pretende.
Steve Kallestad 15/01/14
6

Não se esqueça que no Oracle, desde que os atributos da chave de junção tenham o mesmo nome nas duas tabelas, você também pode escrever isso como:

select *
from Table1 inner join Table2 using (ID);

Isso também tem o mesmo plano de consulta, é claro.

cheduardo
fonte
Retrocedi a edição porque a revisão anterior alterou o significado da resposta
juan
5

Em um cenário em que as tabelas estão na terceira forma normal, as junções entre as tabelas não devem mudar. Ou seja, junte-se a CLIENTES e PAGAMENTOS sempre devem permanecer os mesmos.

No entanto, devemos distinguir junções de filtros . Associações são sobre relacionamentos e filtros são sobre particionamento de um todo.

Alguns autores, referindo-se ao padrão (por exemplo, Jim Melton; Alan R. Simon (1993). Entendendo o novo SQL: um guia completo. Morgan Kaufmann. Pp. 11-12. ISBN 978-1-55860-245-8.) , escreveu sobre os benefícios de adotar a sintaxe JOIN em tabelas separadas por vírgula na cláusula FROM.

Eu concordo totalmente com este ponto de vista.

Existem várias maneiras de escrever SQL e obter os mesmos resultados, mas para muitos daqueles que trabalham em equipe, a legibilidade do código-fonte é um aspecto importante e certamente separa como as tabelas se relacionam entre si de filtros específicos, foi um grande salto no sentido de esclarecer a origem. código.

abrittaf
fonte
Junção interna em significa junção cruzada onde. Vírgula é junção cruzada com precedência mais baixa que junções de palavras-chave. On vs "filter" é irrelevante para junção interna. NFs são irrelevantes para consulta. Nada no padrão promove junções de palavras-chave por vírgula. Otimizações triviais tratam sobre e onde. Esta resposta é um monte de equívocos.
philipxy
1) Acho que @philipxy está tentando dizer "Na cláusula FROM, as tabelas separadas por vírgula têm o mesmo significado que as tabelas CROSS JOINed". Eu concordo com isso. Obviamente, você pode manter a sintaxe antiga e isso pode coexistir com as cláusulas JOIN. Os otimizadores do RDBMS entenderão perfeitamente os dois casos como os mesmos (caso sejam equivalentes, é claro) e elaborarão o mesmo plano.
abrittaf
4

No PostgreSQL, definitivamente não há diferença - ambos equivalem ao mesmo plano de consulta. Tenho 99% de certeza de que também é o caso da Oracle.

Nick Johnson
fonte
2

As duas junções internas fazem a mesma coisa, basta usar a sintaxe ANSI mais recente.

Bob Gettys
fonte
2

Funcionalmente, eles são os mesmos que foram mencionados. Concordo, porém, que fazer a junção é melhor para descrever exatamente o que você deseja fazer. Muitas vezes pensei que sabia como queria consultar algo até começar a fazer as junções e percebi que queria fazer uma consulta diferente da original na minha cabeça.

MattC
fonte
1

É verdade que, funcionalmente, as duas consultas devem ser processadas da mesma maneira. No entanto, a experiência mostrou que, se você estiver selecionando uma das visões que usam a nova sintaxe de junção, é importante estruturar suas consultas também. O otimizador da Oracle pode ficar confuso se uma visão usar uma instrução "join", mas uma consulta acessando a visão usa o método tradicional de associação na cláusula "where".

JoshL
fonte
Isso é mais um problema com visualizações do que com junções.
inexistente 29/09/08
0

Embora a identidade de duas consultas pareça óbvia, às vezes algumas coisas estranhas acontecem. Eu vim para a consulta que possui planos de execução diferentes ao mover o predicado de junção de JOIN para WHERE no Oracle 10g (para o plano WHERE é melhor), mas não consigo reproduzir esse problema em tabelas e dados simplificados. Eu acho que depende dos meus dados e estatísticas. O Optimizer é um módulo bastante complexo e às vezes se comporta magicamente.

É por isso que não podemos responder a essa pergunta em geral, porque depende dos dados internos do banco de dados. Mas devemos saber que a resposta deve ser ' sem diferenças '.

greatvovan
fonte
0

Hoje eu tive esse dilema ao inspecionar o tempo limite de um de nossos sp na produção, alterei uma junção interna em uma tabela criada a partir de um feed xml para uma cláusula 'where' em vez disso ... antes que o exec médio fosse de 2,2 segundos ... a principal diferença no plano de execução é o desaparecimento de uma pesquisa de chave ... A mensagem é que você não saberá até testar os dois métodos.

Felicidades.

trbullet81
fonte
0

Como disse o kiewik, o plano de execução é o mesmo.

A instrução JOIN é apenas mais fácil de ler, tornando mais fácil não esquecer a condição ON e obter um produto cartesiano. Esses erros podem ser bastante difíceis de detectar em consultas longas usando várias associações do tipo: SELECT * FROM t1, t2 WHERE t1.id = t2.some_field.

Se você esquecer apenas uma condição de associação, terá uma consulta muito longa para executar retornando muitos registros ... realmente muitos. Algumas pessoas usam um DISTINCT para corrigir a consulta, mas ainda é muito longo para executar.

É exatamente por isso que usar a instrução JOIN é certamente a melhor prática: uma melhor manutenção e uma melhor legibilidade.

Além disso, se bem me lembro, JOIN é otimizado em relação ao uso de memória.

ROQUEFORT François
fonte
0

Eu tenho um complemento para essa boa resposta :

Isso é o que é definido como SQL92 e SQL89, respectivamente, não há diferença de desempenho entre eles, embora você possa omitir a palavra INNER (usar apenas JOIN é suficientemente claro e, na consulta mais simples, você salva 5 pressionamentos de teclado agora imagine quantos pressionamentos existem em grandes uns).

Ivanzinho
fonte