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]
如果內表正確編制索引,那麼這裏的子查詢根本不是「嚴格意義上的」執行「。
由於子查詢是IN
表達式的一部分,因此將條件推入子查詢中並將其轉換爲EXISTS
。
事實上,這種子查詢每一步的評估:
EXISTS
(
SELECT NULL
FROM [...]
WHERE id = table1.id
)
實際上,你可以看到它在由EXPLAIN EXTENDED
提供的詳細描述。
這就是爲什麼它被稱爲DEPENDENT SUBQUERY
:每次評估的結果取決於table1.id
的值。子查詢本身不相關,它是相關的優化版本。
MySQL
總是在更簡單的過濾器之後評估EXISTS
子句(因爲它們更容易評估,並且有可能根本不評估子查詢)。
如果你想在子查詢一次全部進行評估,重寫查詢,因爲這:
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]
這迫使子查詢被領先的加盟,這是更有效的,如果比較的子查詢小到table_1
,如果子查詢比table_1
大,則效率較低。
如果在子查詢中使用的[...].id
上有索引,則子查詢將使用INDEX FOR GROUP-BY
執行。
按下子查詢的問題是,如果子查詢依賴於外部查詢的常量部分,則這是不可能的(請參閱https://stackoverflow.com/questions/44859809/how-to-optimize-dependent-subquery -with-constant-expression) – andig 2017-07-01 10:43:06