Eu sou um usuário antigo do MySQL e sempre preferi JOIN
a subconsulta. Mas hoje em dia todo mundo usa subconsulta, e eu odeio isso; Não sei porque.
Não tenho o conhecimento teórico para julgar por mim mesmo se há alguma diferença. Uma subconsulta é tão boa quanto uma JOIN
e, portanto, não há nada com que se preocupar?
Respostas:
Retirado do manual do MySQL ( 13.2.10.11 Reescrevendo subconsultas como associações ):
Portanto, as subconsultas podem ser mais lentas que
LEFT [OUTER] JOIN
, mas, na minha opinião, a força delas é uma legibilidade um pouco maior.fonte
Join
esub query
tem sintaxe diferente, portanto, a legibilidade não podemos comparar, ambas têm maior legibilidade, desde que você seja bom na sintaxe SQL. O desempenho é mais importante.As subconsultas são a maneira logicamente correta de resolver problemas do formulário "Obter fatos de A, condicional aos fatos de B". Nesses casos, faz mais sentido lógico colocar B em uma subconsulta do que fazer uma associação. Também é mais seguro, no sentido prático, já que você não precisa ser cauteloso ao obter fatos duplicados de A devido a várias partidas contra B.
Praticamente falando, no entanto, a resposta geralmente se resume ao desempenho. Alguns otimizadores sugam limões quando recebem uma junção versus uma subconsulta, e outros sugam limões de outra maneira, e isso é específico do otimizador, específico da versão do DBMS e específico da consulta.
Historicamente, as junções explícitas geralmente vencem, daí a sabedoria estabelecida de que as junções são melhores, mas os otimizadores estão melhorando o tempo todo e, portanto, prefiro escrever as consultas primeiro de uma maneira logicamente coerente e depois reestruturar se as restrições de desempenho justificarem isso.
fonte
select custid from cust join bought using (custid) where price > 500
. Se um cliente comprou vários itens caros, você receberá dobradas. Para consertar issoselect custid from cust where exists (select * from bought where custid = cust.custid and price > 500)
,. Você pode usarselect distinct …
, mas geralmente é mais trabalhoso, tanto para o otimizador quanto para o avaliador.Na maioria dos casos,
JOIN
s são mais rápidos que as subconsultas e é muito raro uma subconsulta ser mais rápida.No
JOIN
s, o RDBMS pode criar um plano de execução melhor para sua consulta e prever quais dados devem ser carregados para serem processados e economizar tempo, ao contrário da subconsulta em que ele executará todas as consultas e carregará todos os dados para fazer o processamento. .O bom das subconsultas é que elas são mais legíveis que
JOIN
s: é por isso que a maioria das pessoas novas do SQL prefere; é o caminho mais fácil; mas quando se trata de desempenho, o JOINS é melhor na maioria dos casos, mesmo que também não seja difícil de ler.fonte
select * from a where a.x = (select b.x form b where b.id = a.id)
é extremamente pequeno comparado a uma junção. Esse é um problema muito específico, mas, em alguns casos, leva você de horas a minutos.Use EXPLAIN para ver como seu banco de dados executa a consulta em seus dados. Existe uma enorme "depende" nesta resposta ...
O PostgreSQL pode reescrever uma subconsulta em uma junção ou uma junção em uma subconsulta quando achar que uma é mais rápida que a outra. Tudo depende dos dados, índices, correlação, quantidade de dados, consulta, etc.
fonte
No ano de 2010, eu teria me juntado ao autor dessas perguntas e teria votado fortemente
JOIN
, mas com muito mais experiência (especialmente no MySQL), posso afirmar: Sim, as subconsultas podem ser melhores. Eu li várias respostas aqui; algumas subconsultas declaradas são mais rápidas, mas faltavam uma boa explicação. Espero poder fornecer uma com esta (muito) resposta tardia:Antes de mais, deixe-me dizer o mais importante: existem diferentes formas de subconsultas
E a segunda declaração importante: o tamanho importa
Se você usar subconsultas, esteja ciente de como o DB-Server executa a subconsulta. Especialmente se a subconsulta for avaliada uma vez ou para cada linha! Por outro lado, um servidor de banco de dados moderno é capaz de otimizar muito. Em alguns casos, uma subconsulta ajuda a otimizar uma consulta, mas uma versão mais recente do DB-Server pode tornar a otimização obsoleta.
Subconsultas em campos selecionados
Esteja ciente de que uma subconsulta é executada para cada linha resultante
foo
.Evite isso, se possível; isso pode diminuir drasticamente a sua consulta em grandes conjuntos de dados. No entanto, se a subconsulta não tiver nenhuma referência,
foo
ela poderá ser otimizada pelo servidor de banco de dados como conteúdo estático e poderá ser avaliada apenas uma vez.Subconsultas na instrução Where
Se você tiver sorte, o banco de dados otimiza isso internamente em um
JOIN
. Caso contrário, sua consulta se tornará muito, muito lenta em grandes conjuntos de dados, porque executará a subconsulta para cada linhafoo
, não apenas os resultados, como no tipo de seleção.Subconsultas na instrução Join
Isto é interessante. Combinamos
JOIN
com uma subconsulta. E aqui temos a força real das subconsultas. Imagine um conjunto de dados com milhões de linhas,wilco
mas apenas algumas distintasme
. Em vez de ingressar em uma mesa enorme, agora temos uma mesa temporária menor para participar. Isso pode resultar em consultas muito mais rápidas, dependendo do tamanho do banco de dados. Você pode ter o mesmo efeito comCREATE TEMPORARY TABLE ...
eINSERT INTO ... SELECT ...
, o que pode fornecer melhor legibilidade em consultas muito complexas (mas pode bloquear conjuntos de dados em um nível de isolamento de leitura repetível).Subconsultas aninhadas
Você pode aninhar subconsultas em vários níveis. Isso pode ajudar em grandes conjuntos de dados se você precisar agrupar ou classificar os resultados. Normalmente, o servidor de banco de dados cria uma tabela temporária para isso, mas às vezes você não precisa classificar a tabela inteira, apenas o conjunto de resultados. Isso pode fornecer um desempenho muito melhor, dependendo do tamanho da tabela.
Conclusão
As subconsultas não substituem a
JOIN
e você não deve usá-las dessa maneira (embora possível). Na minha humilde opinião, o uso correto de uma subconsulta é o uso como uma substituição rápida deCREATE TEMPORARY TABLE ...
. Uma boa subconsulta reduz um conjunto de dados de uma maneira que você não pode realizar naON
instrução aJOIN
. Se uma sub-consulta tem uma das palavras-chaveGROUP BY
ouDISTINCT
, de preferência não está situado nos campos selecionados ou a declaração em que, em seguida, pode melhorar o desempenho muito.fonte
Sub-queries in the Join-statement
: (1) gerar tabela derivada a partir da própria subconsulta pode demorar muito tempo. (2) a tabela derivada resultante não é indexada. esses dois por si só podem desacelerar significativamente o SQL.10
registros, já que não há índice, isso ainda significa potencialmente consultar 9 vezes mais registros de dados do que a tabela temporária ao ingressar em outras tabelas. BTW eu tive esse problema antes com o meu db (MySQL), no meu caso, usando subconsulta emSELECT list
poderia ser muito mais rápido.EXPLAIN
em uma consulta antes de otimizar. Com o antigo,set profiling=1
você pode ver facilmente, se uma tabela temporária é um gargalo. E mesmo que um índice precise de tempo de processamento, as B-Trees otimizam a consulta de registros, mas uma tabela de 10 registros pode ser muito mais rápida que um índice para milhões de registros. Mas isso depende de vários fatores, como tamanhos e tipos de campos.Antes de tudo, para comparar os dois primeiro, você deve distinguir consultas com subconsultas para:
Para a primeira classe de consultas, um bom RDBMS verá junções e subconsultas como equivalentes e produzirá os mesmos planos de consulta.
Hoje em dia, até o mysql faz isso.
Ainda assim, às vezes isso não acontece, mas isso não significa que as junções sempre vencerão - eu tive casos ao usar subconsultas no mysql para melhorar o desempenho. (Por exemplo, se houver algo impedindo o planejador do mysql estimar corretamente o custo e se o planejador não vir a variante de junção e a variante de subconsulta da mesma forma, as subconsultas poderão superar as junções forçando um determinado caminho).
A conclusão é que você deve testar suas consultas para as variantes de junção e subconsulta, se quiser ter certeza de qual delas terá um desempenho melhor.
Para a segunda classe, a comparação não faz sentido, pois essas consultas não podem ser reescritas usando junções e, nesses casos, as subconsultas são uma maneira natural de executar as tarefas necessárias e você não deve discriminá-las.
fonte
Eu acho que o que foi subestimado nas respostas citadas é a questão de duplicatas e resultados problemáticos que podem surgir de casos específicos (de uso).
(embora Marcelo Cantos o mencione)
Citarei o exemplo dos cursos Lagunita de Stanford sobre SQL.
Tabela do aluno
Aplicar tabela
(pedidos feitos para universidades e cursos específicos)
Vamos tentar encontrar as pontuações do GPA para estudantes que se inscreveram no ensino médio
CS
(independentemente da universidade)Usando uma subconsulta:
O valor médio para este conjunto de resultados é:
Usando uma junção:
valor médio para este conjunto de resultados:
É óbvio que a segunda tentativa produz resultados enganosos em nosso caso de uso, uma vez que conta duplicatas para o cálculo do valor médio. Também é evidente que o uso da
distinct
declaração baseada em junção não eliminará o problema, pois manterá erroneamente uma das três ocorrências da3.9
pontuação. O caso correto é contabilizar DUAS (2) ocorrências da3.9
pontuação, uma vez que realmente temos DOIS (2) alunos com essa pontuação que atendem aos nossos critérios de consulta.Parece que, em alguns casos, uma subconsulta é o caminho mais seguro, além de quaisquer problemas de desempenho.
fonte
A documentação do MSDN para SQL Server diz
então se você precisar de algo como
tente usar join. Em outros casos, não faz diferença.
Eu digo: A criação de funções para subconsultas elimina o problema do cluttter e permite implementar lógica adicional nas subconsultas. Portanto, recomendo criar funções para subconsultas sempre que possível.
A desordem no código é um grande problema e a indústria trabalha para evitá-lo há décadas.
fonte
NOT EXISTS
. ANOT EXISTS
vence umaLEFT OUTER JOIN
por várias razões: desempenho, segurança contra falhas (no caso de colunas nuláveis) e legibilidade. sqlperformance.com/2012/12/t-sql-queries/left-anti-semi-joinExecute em um banco de dados muito grande a partir de um antigo Mambo CMS:
0 segundos
~ 3 segundos
Um EXPLAIN mostra que eles examinam exatamente o mesmo número de linhas, mas um leva 3 segundos e o outro é quase instantâneo. Moral da história? Se o desempenho é importante (quando não é?), Tente de várias maneiras e veja qual é o mais rápido.
E...
0 segundos
Novamente, mesmos resultados, mesmo número de linhas examinadas. Meu palpite é que DISTINCT mos_content.catid leva muito mais tempo para descobrir do que DISTINCT mos_categories.id.
fonte
id
e não algo como essecatid
? Tentando otimizar meus acessos db, e seus aprendizados podem ajudar.Conforme minha observação, como dois casos, se uma tabela tiver menos de 100.000 registros, a junção funcionará rapidamente.
Porém, no caso de uma tabela ter mais de 100.000 registros, uma subconsulta é o melhor resultado.
Eu tenho uma tabela que possui 500.000 registros que criei abaixo da consulta e seu tempo de resultado é como
fonte
As subconsultas geralmente são usadas para retornar uma única linha como um valor atômico, embora possam ser usadas para comparar valores com várias linhas com a palavra-chave IN. Eles são permitidos em praticamente qualquer ponto significativo em uma instrução SQL, incluindo a lista de destino, a cláusula WHERE e assim por diante. Uma subconsulta simples pode ser usada como condição de pesquisa. Por exemplo, entre um par de tabelas:
Observe que o uso de um operador de valor normal nos resultados de uma subconsulta requer que apenas um campo seja retornado. Se você estiver interessado em verificar a existência de um único valor em um conjunto de outros valores, use IN:
Isso é obviamente diferente de, digamos, LEFT-JOIN, no qual você apenas deseja juntar itens das tabelas A e B, mesmo que a condição de junção não encontre nenhum registro correspondente na tabela B, etc.
Se você está preocupado apenas com a velocidade, precisará verificar com o banco de dados e escrever uma boa consulta e verificar se há alguma diferença significativa no desempenho.
fonte
Versão do MySQL: 5.5.28-0ubuntu0.12.04.2-log
Também tive a impressão de que JOIN é sempre melhor que uma subconsulta no MySQL, mas EXPLAIN é a melhor maneira de fazer um julgamento. Aqui está um exemplo em que as subconsultas funcionam melhor que JOINs.
Aqui está minha consulta com 3 subconsultas:
EXPLAIN mostra:
A mesma consulta com JOINs é:
e a saída é:
Uma comparação da
rows
coluna indica a diferença e a consulta com JOINs está usandoUsing temporary; Using filesort
.Obviamente, quando executo as duas consultas, a primeira é feita em 0,02 segundos, a segunda não é concluída mesmo após 1 minuto, por isso EXPLAIN explicou essas consultas corretamente.
Se eu não tiver o INNER JOIN na
list_tag
mesa, ou seja, se eu removerda primeira consulta e correspondentemente:
a partir da segunda consulta, EXPLAIN retorna o mesmo número de linhas para ambas as consultas e essas consultas são executadas igualmente rápido.
fonte
As subconsultas têm a capacidade de calcular funções de agregação rapidamente. Por exemplo, encontre o preço mínimo do livro e obtenha todos os livros vendidos com esse preço. 1) Usando subconsultas:
2) usando JOINs
fonte
GROUP BY
s com tabelas diferentes: stackoverflow.com/questions/11415284/… As subconsultas parecem ser estritamente mais gerais. Veja também o homem do MySQL: dev.mysql.com/doc/refman/5.7/en/optimizing-subqueries.html | dev.mysql.com/doc/refman/5.7/en/rewriting-subqueries.htmlAlgumas pessoas dizem que "alguns RDBMS podem reescrever uma subconsulta em uma associação ou uma associação a uma subconsulta quando achar que uma é mais rápida que a outra.", Mas essa declaração se aplica a casos simples, certamente não para consultas complicadas com subconsultas que realmente causam uma problemas no desempenho.
fonte
A diferença é vista apenas quando a segunda tabela de junção possui significativamente mais dados que a tabela principal. Eu tive uma experiência como abaixo ...
Tivemos uma tabela de usuários com cem mil entradas e seus dados de associação (amizade) com cerca de 300 mil entradas. Foi uma declaração de junção para levar os amigos e seus dados, mas com um grande atraso. Mas estava funcionando bem, onde havia apenas uma pequena quantidade de dados na tabela de associação. Depois que o alteramos para usar uma subconsulta, funcionou bem.
Entretanto, as consultas de junção estão funcionando com outras tabelas que possuem menos entradas que a tabela principal.
Então, acho que as instruções de junção e subconsulta estão funcionando bem e isso depende dos dados e da situação.
fonte
Hoje em dia, muitos dbs podem otimizar subconsultas e associações. Portanto, basta examinar sua consulta usando o Explique e veja qual é mais rápida. Se não houver muita diferença no desempenho, prefiro usar a subconsulta, pois elas são simples e fáceis de entender.
fonte
Estou apenas pensando no mesmo problema, mas estou usando subconsulta na parte FROM. Eu preciso conectar e consultar de tabelas grandes, a tabela "escrava" tem 28 milhões de registros, mas o resultado é apenas 128, portanto, resultado tão pequeno quanto o big data! Estou usando a função MAX () nele.
Primeiro estou usando LEFT JOIN porque acho que é o caminho correto, o mysql pode otimizar etc. Segunda vez apenas para teste, reescrevo para sub-selecionar contra o JOIN.
Tempo de execução LEFT JOIN: 1.12s Tempo de execução SUB-SELECT: 0.06s
A subseleção 18 vezes mais rápida que a junção! Apenas no adv chokito. A subseleção parece terrível, mas o resultado ...
fonte
Se você deseja acelerar sua consulta usando join:
Para "junção interna / junção", não use a condição where, em vez disso, use-a na condição "ON". Por exemplo:
Para "Junção esquerda / direita", não use na condição "ATIVADO", pois se você usar a junção esquerda / direita, todas as linhas serão exibidas para qualquer tabela. Então, tente usar a condição "Onde"
fonte