Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

IN vs. JOIN com conjuntos de linhas grandes


Atualização:

Este artigo no meu blog resume minha resposta e meus comentários a outras respostas e mostra os planos reais de execução:
SELECT  *
FROM    a
WHERE   a.c IN (SELECT d FROM b)

SELECT  a.*
FROM    a
JOIN    b
ON      a.c = b.d

Essas consultas não são equivalentes. Eles podem gerar resultados diferentes se sua tabela b não é preservada por chave (ou seja, os valores de b.d não são únicos).

O equivalente da primeira consulta é o seguinte:
SELECT  a.*
FROM    a
JOIN    (
        SELECT  DISTINCT d
        FROM    b
        ) bo
ON      a.c = bo.d

Se b.d é UNIQUE e marcado como tal (com um UNIQUE INDEX ou UNIQUE CONSTRAINT ), essas consultas são idênticas e provavelmente usarão planos idênticos, pois SQL Server é inteligente o suficiente para levar isso em conta.

SQL Server pode empregar um dos seguintes métodos para executar esta consulta:

  • Se houver um índice em a.c , d é UNIQUE e b é relativamente pequeno comparado a a , então a condição é propagada para a subconsulta e o INNER JOIN simples é usado (com b conduzindo)

  • Se houver um índice em b.d e d não é UNIQUE , então a condição também é propagada e LEFT SEMI JOIN é usado. Também pode ser usado para a condição acima.

  • Se houver um índice em ambos b.d e a.c e eles são grandes, então MERGE SEMI JOIN é usado

  • Se não houver índice em nenhuma tabela, uma tabela de hash será construída em b e HASH SEMI JOIN é usado.

Nenhum desses métodos reavalia toda a subconsulta a cada vez.

Veja esta entrada no meu blog para mais detalhes sobre como isso funciona:

Existem links para todos os RDBMS dos quatro grandes.