Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Kann ich MySQL zwingen, zuerst eine Unterabfrage auszuführen?

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]

Wenn die innere Tabelle richtig indiziert ist, wird die Unterabfrage hier im strengen Sinne des Wortes überhaupt nicht "ausgeführt".

Da die Unterabfrage Teil eines IN ist -Ausdruck wird die Bedingung in die Unterabfrage verschoben und in ein EXISTS umgewandelt .

Tatsächlich wird diese Unterabfrage bei jedem Schritt ausgewertet:

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

Sie können es tatsächlich in der detaillierten Beschreibung sehen, die von EXPLAIN EXTENDED bereitgestellt wird .

Deshalb heißt es DEPENDENT SUBQUERY :Das Ergebnis jeder Auswertung hängt vom Wert von table1.id ab . Die Unterabfrage als solche ist nicht korreliert, es ist die optimierte Version, die korreliert ist.

MySQL wertet immer EXISTS aus -Klausel nach den einfacheren Filtern (da sie viel einfacher auszuwerten sind und die Wahrscheinlichkeit besteht, dass die Unterabfrage überhaupt nicht ausgewertet wird).

Wenn Sie möchten, dass die Unterabfrage auf einmal ausgewertet wird, schreiben Sie die Abfrage wie folgt um:

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]

Dies erzwingt, dass die Unterabfrage im Join führend ist, was effizienter ist, wenn die Unterabfrage im Vergleich zu table_1 klein ist und weniger effizient, wenn die Unterabfrage im Vergleich zu table_1 groß ist .

Wenn es einen Index auf [...].id gibt in der Unterabfrage verwendet wird, wird die Unterabfrage mit einem INDEX FOR GROUP-BY durchgeführt .