sql >> Databasteknik >  >> RDS >> Sqlserver

IN vs. JOIN med stora raduppsättningar

Uppdatering:

Den här artikeln i min blogg sammanfattar både mitt svar och mina kommentarer till andra svar, och visar faktiska genomförandeplaner:

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

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

Dessa frågor är inte likvärdiga. De kan ge olika resultat om din tabell b är inte nyckelbevarad (dvs. värdena för b.d är inte unika).

Motsvarigheten till den första frågan är följande:

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

Om b.d är UNIQUE och markerad som sådan (med ett UNIQUE INDEX eller UNIQUE CONSTRAINT ), då är dessa frågor identiska och kommer troligen att använda identiska planer, eftersom SQL Server är smart nog att ta hänsyn till detta.

SQL Server kan använda en av följande metoder för att köra den här frågan:

  • Om det finns ett index på a.c , d är UNIQUE och b är relativt liten jämfört med a , sedan sprids villkoret till underfrågan och den vanliga INNER JOIN används (med b ledande)

  • Om det finns ett index på b.d och d är inte UNIQUE , då sprids även villkoret och LEFT SEMI JOIN är använd. Den kan också användas för tillståndet ovan.

  • Om det finns ett index på båda b.d och a.c och de är stora, sedan MERGE SEMI JOIN används

  • Om det inte finns något index på någon tabell byggs en hashtabell på b och HASH SEMI JOIN används.

Intedera av dessa metoder omvärderar hela underfrågan varje gång.

Se det här inlägget i min blogg för mer information om hur detta fungerar:

Det finns länkar för alla RDBMS är av de fyra stora.



  1. Operand bör innehålla 1 kolumn - MySQL NOT IN

  2. värde för långt för typ tecken varierande (100)----nyligen bytte databas, gjorde ingenting i db

  3. MYSQL Inner Sammanfoga två bord över två nycklar

  4. Hur returnerar jag heltal och numeriska kolumner från MySQL som heltal och numeriska i PHP?