MySQL 優化器認為:「將外層條件下推到子查詢,可用索引精準查找,比全表掃描外層再逐行執行子查詢更高效。」
但現實是:外層表巨大 (90 萬),子查詢無法有效利用索引,導致 90 萬 × 子查詢成本 的災難性複雜度。
SELECT * FROM t1
WHERE t1.col1 IN (
SELECT t2.col2 FROM t2 WHERE t2.col3 = t1.col4
);
SELECT t1.*
FROM t1
INNER JOIN t2 ON t2.col3 = t1.col4
WHERE t2.col2 IS NOT NULL; -- 視語意調整
SELECT t1.*
FROM t1
JOIN (
SELECT DISTINCT col3, col2 FROM t2 WHERE col2 IS NOT NULL
) dt ON dt.col3 = t1.col4;
WITH dt AS (
SELECT DISTINCT col3, col2 FROM t2 WHERE col2 IS NOT NULL
)
SELECT t1.* FROM t1 JOIN dt ON dt.col3 = t1.col4;
SELECT * FROM t1
WHERE EXISTS (
SELECT 1 FROM t2 WHERE t2.col3 = t1.col4 AND t2.col2 IS NOT NULL
);
MySQL 5.6-8.0 對關聯子查詢優化有限。能用 JOIN/CTE 改寫就改寫,將「逐行執行」變為「集合運算」。8.0 引入Materialized CTE和Semi-join優化,但複雜關聯子查詢仍建議手工改寫。
-- 慢查詢日誌中尋找 Dependent Subquery
SELECT * FROM mysql.slow_log
WHERE sql_text LIKE '%DEPENDENT SUBQUERY%'
OR sql_text LIKE '%correlated%';