sql >> Databasteknik >  >> RDS >> Mysql

Kan jag tvinga mysql att utföra subquery först?

SELECT  `table_1`.*
FROM    `table_1`
INNER JOIN
        `table_2` [...]
INNER JOIN
        `table_3` [...]
WHERE   `table_1`.`id` IN
        (
        SELECT  `id`
        FROM    [...]
        )
        AND [more conditions]

Om den inre tabellen är korrekt indexerad, "utförs" underfrågan här inte alls i en strikt mening av ordet.

Eftersom underfrågan är en del av en IN uttryck, skjuts villkoret in i underfrågan och det omvandlas till en EXISTS .

Faktum är att den här underfrågan utvärderas i varje steg:

EXISTS
(
SELECT  NULL
FROM    [...]
WHERE   id = table1.id
)

Du kan faktiskt se det i den detaljerade beskrivningen som tillhandahålls av EXPLAIN EXTENDED .

Det är därför det kallas DEPENDENT SUBQUERY :resultatet av varje utvärdering beror på värdet av table1.id . Underfrågan som sådan är inte korrelerad, det är den optimerade versionen som är korrelerad.

MySQL utvärderar alltid EXISTS klausul efter de enklare filtren (eftersom de är mycket lättare att utvärdera och det finns en sannolikhet att underfrågan inte kommer att utvärderas alls).

Om du vill att underfrågan ska utvärderas på en gång, skriv om frågan så här:

SELECT  table_1.*
FROM    (
        SELECT  DISTINCT id
        FROM    [...]
        ) q
JOIN    table_1
ON      table_1.id = q.id
JOIN    table_2
ON      [...]
JOIN    table_3
ON      [...]
WHERE   [more conditions]

Detta tvingar underfrågan att vara ledande i kopplingen, vilket är mer effektivt om underfrågan är liten jämfört med table_1 , och mindre effektiv om underfrågan är stor jämfört med table_1 .

Om det finns ett index på [...].id används i underfrågan, kommer underfrågan att utföras med en INDEX FOR GROUP-BY .



  1. Använd en pl-sql-procedur eller markör för att välja topp 3-rankning

  2. Innebär en postgres främmande nyckel ett index?

  3. Hur ansluter du till en MySQL-databas med Oracle SQL Developer?

  4. Skapa unika slumpmässiga alfanumeriska tecken som är 7 tecken långa