Associações explícitas x implícitas


399

Existe alguma diferença de eficiência em uma junção interna explícita vs implícita? Por exemplo:

SELECT * FROM
table a INNER JOIN table b
ON a.id = b.id;

vs.

SELECT a.*, b.*
FROM table a, table b
WHERE a.id = b.id;

11
Boa pergunta. Estou curioso para saber por que a junção explícita é usada. Não é possível fazer todas as consultas sem ele?
andrew 23/01

6
Usar Explique palavra-chave para saber a diferença sobre ambas as consultas .. uso Cadastre-se e veja a diferença .. Se você tentar em uma mesa de mais de 100 mil registros você pode ver a diferença ...
Jeyanth Kumar

@ Andrew Minha pergunta era, na verdade, se implícita juntar-se era uma forma de "hack" (como em "? Uma consulta que envolve mais de uma tabela, não usando uma junção Isso é um hack não é?")
bobobobo

3
Eles são diferentes, a união implícita o surpreenderá de vez em quando ao lidar com valores nulos; use junção explícita e evite erros que surjam quando "nada mudou!"
BlackTigerX

11
Não há diferença. ,é CROSS JOINcom a ligação mais solto e INNER JOINé CROSS JOINcom ONgosto WHEREmas mais apertado vinculativo. O que importa para a execução é como o DBMS otimiza as consultas.
philipxy

Respostas:


132

Em termos de desempenho, eles são exatamente os mesmos (pelo menos no SQL Server).

PS: Lembre-se de que a IMPLICIT OUTER JOINsintaxe está obsoleta desde o SQL Server 2005. (A IMPLICIT INNER JOINsintaxe usada na pergunta ainda é suportada)

Descontinuação do "estilo antigo" Sintaxe JOIN: apenas uma coisa parcial


4
@lomaxx, apenas por uma questão de clareza, você poderia especificar qual sintaxe dos 2 da pergunta está obsoleta?
J Wynia 5/09/08

8
Você pode fornecer documentação de suporte? Isso parece errado em vários níveis.
NotMe

21
Como você desaprova o padrão SQL?
David Crawshaw

7
@david Crenshaw, a associação implícita não está mais no padrão e não existe há 18 anos.
HLGEM

11
As chamadas "junções implícitas" da variedade "interior" ou "cruz" permanecem no Padrão. O SQL Server está preterindo a sintaxe de junção externa "à moda antiga" (isto é, *=e =*) que nunca foi Padrão.
precisa saber é o seguinte

129

Pessoalmente, prefiro a sintaxe de junção, pois torna mais claro que as tabelas são unidas e como elas são unidas. Tente comparar consultas SQL maiores em que você seleciona 8 tabelas diferentes e há muita filtragem no local. Usando a sintaxe de junção, você separa as partes em que as tabelas estão unidas e a parte em que você está filtrando as linhas.


4
Concordo plenamente, mas isso é meio fora de tópico. O OP perguntou sobre eficiência.
villasv

56

No MySQL 5.1.51, ambas as consultas têm planos de execução idênticos:

mysql> explain select * from table1 a inner join table2 b on a.pid = b.pid;
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref          | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
|  1 | SIMPLE      | b     | ALL  | PRIMARY       | NULL | NULL    | NULL         |  986 |       |
|  1 | SIMPLE      | a     | ref  | pid           | pid  | 4       | schema.b.pid |   70 |       |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
2 rows in set (0.02 sec)

mysql> explain select * from table1 a, table2 b where a.pid = b.pid;
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
| id | select_type | table | type | possible_keys | key  | key_len | ref          | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
|  1 | SIMPLE      | b     | ALL  | PRIMARY       | NULL | NULL    | NULL         |  986 |       |
|  1 | SIMPLE      | a     | ref  | pid           | pid  | 4       | schema.b.pid |   70 |       |
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+
2 rows in set (0.00 sec)

table1tem 166208 linhas; table2tem cerca de 1000 linhas.

Este é um caso muito simples; de forma alguma prova que o otimizador de consultas não ficaria confuso e geraria planos diferentes em um caso mais complicado.


Essa deve ser a resposta aceita. Isso está correto, o plano é o mesmo (ou próximo a declarações maiores), mas a quantidade de registros será drástica, causando diferença no desempenho.
SovietFrontier 13/05/19

37

A segunda sintaxe tem a possibilidade indesejada de uma junção cruzada: você pode adicionar tabelas à parte FROM sem a cláusula WHERE correspondente. Isso é considerado prejudicial.


E se os nomes de tabela na cláusula from forem gerados a partir das tabelas usadas na cláusula where?
precisa saber é o seguinte

você também pode fazer uma junção cruzada com a sintaxe explícita JOIN. ( stackoverflow.com/a/44438026/929164 ) Provavelmente, você quis dizer que ela é menos rigorosa e, portanto, mais propensa a erros do usuário.
Daniel Dubovski

15

A primeira resposta que você deu usa o que é conhecido como sintaxe de junção ANSI, a outra é válida e funcionará em qualquer banco de dados relacional.

Concordo com o grom que você deve usar a sintaxe de junção ANSI. Como eles disseram, a principal razão é a clareza. Em vez de ter uma cláusula where com muitos predicados, alguns dos quais associam tabelas e outros restringem as linhas retornadas com a sintaxe de associação ANSI, você deixa claro que condições estão sendo usadas para ingressar em suas tabelas e quais estão sendo usadas para restringir o resultados.


5

Em termos de desempenho, eles são exatamente os mesmos (pelo menos no SQL Server), mas lembre-se de que estão obsoletos nessa sintaxe de junção e não são suportados pelo sql server2005 imediatamente.

Eu acho que você está pensando nos operadores obsoletos * = e = * vs. "junção externa".

Acabei de testar os dois formatos fornecidos e eles funcionam corretamente em um banco de dados do SQL Server 2008. No meu caso, eles produziram planos de execução idênticos, mas eu não podia dizer com segurança que isso sempre seria verdade.


5

@lomaxx: Apenas para esclarecer, tenho certeza de que as duas sintaxes acima são suportadas pelo SQL Serv 2005. A sintaxe abaixo NÃO é suportada no entanto

select a.*, b.*  
from table a, table b  
where a.id *= b.id;

Especificamente, a junção externa (* =) não é suportada.


2
Francamente, eu não o usaria nem no SQL Server 2000, a sintaxe * = geralmente fornece respostas erradas. Às vezes, ele as interpreta como junções cruzadas.
HLGEM 18/03/09

2

Em alguns bancos de dados (principalmente Oracle), a ordem das junções pode fazer uma enorme diferença para consultar o desempenho (se houver mais de duas tabelas). Em um aplicativo, tivemos literalmente duas ordens de diferença de magnitude em alguns casos. O uso da sintaxe de junção interna fornece controle sobre isso - se você usar a sintaxe correta das dicas.

Você não especificou qual banco de dados está usando, mas a probabilidade sugere o SQL Server ou o MySQL onde não faz diferença real.


11
Leigh, você também pode usar as dicas nas junções implícitas.
SquareCog 30/10/08

11
No Oracle, é extremamente raro a ordem de junção afetar o plano de execução de maneira significativa. Veja este artigo de Jonathan Lewis para uma explicação.
Jon Heller

1

Como Leigh Caldwell afirmou, o otimizador de consulta pode produzir diferentes planos de consulta com base no que funcionalmente se parece com a mesma instrução SQL. Para ler mais sobre isso, dê uma olhada nas duas postagens a seguir:

Uma postagem da equipe do Oracle Optimizer

Outra postagem do blog "Structured Data"

Espero que você ache isso interessante.


Mike, a diferença sobre a qual eles estão falando é que você precisa ter certeza de que, se você especificar uma associação explícita, especificará a condição de associação na qual participar, não o filtro. Você observará que, para consultas semanticamente corretas, o plano exec é o mesmo.
SquareCog 30/10/08

1

Em termos de desempenho, não deve fazer diferença. A sintaxe de junção explícita me parece mais clara, pois define claramente os relacionamentos entre as tabelas na cláusula from e não desordena a cláusula where.


0

Basicamente, a diferença entre os dois é que um é escrito da maneira antiga, enquanto o outro é escrito da maneira moderna. Pessoalmente, prefiro o script moderno usando as definições interna, esquerda, externa e direita, porque elas são mais explicativas e tornam o código mais legível.

Ao lidar com junções internas, também não há diferença real na legibilidade; no entanto, pode ser complicado lidar com junções esquerda e direita, pois no método mais antigo, você obteria algo assim:

SELECT * 
FROM table a, table b
WHERE a.id = b.id (+);

A descrição acima é a maneira antiga de como uma junção esquerda é escrita, em oposição ao seguinte:

SELECT * 
FROM table a 
LEFT JOIN table b ON a.id = b.id;

Como você pode ver visualmente, a maneira moderna de como o script é escrito torna a consulta mais legível. (A propósito, o mesmo vale para as junções direitas e um pouco mais complicado para as junções externas).

Voltando à placa da caldeira, não faz diferença para o compilador SQL a maneira como a consulta é escrita, pois lida com eles da mesma maneira. Eu já vi uma mistura de ambos nos bancos de dados Oracle, que tiveram muitas pessoas escrevendo nele, tanto as mais antigas quanto as mais novas. Novamente, tudo se resume a quão legível é o script e a equipe com a qual você está desenvolvendo.


-1

Na minha experiência, o uso da sintaxe de junção cruzada com um local onde geralmente produz um plano de execução danificado, especialmente se você estiver usando um produto Microsoft SQL. A maneira como o SQL Server tenta estimar a contagem de linhas da tabela, por exemplo, é terrivelmente horrível. O uso da sintaxe de junção interna fornece controle sobre como a consulta é executada. Portanto, do ponto de vista prático, dada a natureza atávica da atual tecnologia de banco de dados, você precisa seguir a junção interna.


5
Você tem alguma prova disso? Porque a resposta aceita diz o contrário.
Cimmanon
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.