Pergunta

Existe alguma diferença de eficiência em uma junção interna explícita e 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;
Foi útil?

Solução

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

PS:Esteja ciente de que o IMPLICIT OUTER JOIN a sintaxe está obsoleta desde o SQL Server 2005.(O IMPLICIT INNER JOIN a sintaxe usada na pergunta ainda é suportada)

Descontinuação da sintaxe JOIN do "estilo antigo":Apenas uma coisa parcial

Outras dicas

Pessoalmente, prefiro a sintaxe de junção, pois deixa mais claro que as tabelas são unidas e como são unidas.Tente comparar consultas SQL maiores, nas quais você seleciona entre 8 tabelas diferentes e tem muita filtragem no local.Ao usar a sintaxe de junção, você separa as partes onde as tabelas são unidas, para a parte onde você está filtrando as linhas.

No MySQL 5.1.51, ambas as consultas possuem 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)

table1 possui 166.208 linhas; table2 tem cerca de 1000 linhas.

Este é um caso muito simples;isso não prova de forma alguma que o otimizador de consulta não se confundiria e geraria planos diferentes em um caso mais complicado.

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

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 disseram, o principal motivo é a clareza.Em vez de ter uma cláusula where com muitos predicados, alguns dos quais unem tabelas e outros restringem as linhas retornadas com a sintaxe de junção ANSI, você está deixando claro quais condições estão sendo usadas para unir suas tabelas e quais estão sendo usadas para restringir o resultados.

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

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

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

Em termos de desempenho, eles são exatamente iguais (pelo menos no SQL Server), mas esteja ciente de que eles estão descontinuando essa sintaxe de junção e ela não é suportada pelo sql server2005 imediatamente.

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

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

Em alguns bancos de dados (principalmente Oracle), a ordem das junções pode fazer uma enorme diferença no desempenho da consulta (se houver mais de duas tabelas).Em uma aplicação, tivemos literalmente duas ordens de magnitude de diferença em alguns casos.Usar a sintaxe de junção interna lhe dá controle sobre isso - se você usar a sintaxe de dicas correta.

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

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

Uma postagem da equipe do Oracle Optimizer

Outra postagem do blog "Dados Estruturados"

Espero que você ache isso interessante.

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

Na minha experiência, usar a sintaxe de junção cruzada com uma cláusula where geralmente produz um plano de execução com danos cerebrais, 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.Usar a sintaxe de junção interna oferece algum 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, é necessário optar pela junção interna.

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 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 ficar complicado ao lidar com junções à esquerda e à direita, pois no método antigo você obteria algo assim:

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

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

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

Como você pode ver visualmente, a forma moderna de escrever o script torna a consulta mais legível.(A propósito, o mesmo vale para junções à direita e um pouco mais complicado para junções externas).

Voltando ao padrão, não faz diferença para o compilador SQL como a consulta é escrita, pois ele as trata da mesma maneira.Já vi uma mistura de ambos nos bancos de dados Oracle, onde muitas pessoas escreveram neles, tanto os mais velhos quanto os mais jovens.Novamente, tudo se resume à legibilidade do script e à equipe com a qual você está desenvolvendo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top