Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

IN vs. JOIN con set di righe grandi

Aggiornamento:

Questo articolo nel mio blog riassume sia la mia risposta che i miei commenti ad altre risposte e mostra i piani di esecuzione effettivi:

SELECT  *
FROM    a
WHERE   a.c IN (SELECT d FROM b)

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

Queste query non sono equivalenti. Possono produrre risultati diversi se la tua tabella b non è conservata la chiave (cioè i valori di b.d non sono univoci).

L'equivalente della prima query è il seguente:

SELECT  a.*
FROM    a
JOIN    (
        SELECT  DISTINCT d
        FROM    b
        ) bo
ON      a.c = bo.d

Se b.d è UNIQUE e contrassegnato come tale (con un UNIQUE INDEX o UNIQUE CONSTRAINT ), quindi queste query sono identiche e molto probabilmente utilizzeranno piani identici, poiché SQL Server è abbastanza intelligente da tenerne conto.

SQL Server può utilizzare uno dei seguenti metodi per eseguire questa query:

  • Se è presente un indice su a.c , d è UNIQUE e b è relativamente piccolo rispetto a a , quindi la condizione viene propagata nella sottoquery e nel semplice INNER JOIN viene utilizzato (con b principale)

  • Se è presente un indice su b.d e d non è UNIQUE , quindi viene propagata anche la condizione e LEFT SEMI JOIN viene usato. Può essere utilizzato anche per la condizione di cui sopra.

  • Se è presente un indice su entrambi b.d e a.c e sono grandi, quindi MERGE SEMI JOIN viene utilizzato

  • Se non è presente alcun indice su nessuna tabella, viene creata una tabella hash su b e HASH SEMI JOIN viene utilizzato.

Nemmeno di questi metodi rivaluta ogni volta l'intera sottoquery.

Vedi questa voce nel mio blog per maggiori dettagli su come funziona:

Ci sono collegamenti per tutti i RDBMS è dei quattro grandi.