MySQL má známé problémy s optimalizací dotazů zahrnujících korelované poddotazy nebo podvýběry. Až do verze 5.6.5 nezhmotňuje poddotazy, ale zhmotní odvozenou tabulku použitou ve spojení.
V podstatě to znamená, že když použijete spojení, při prvním setkání s poddotazem MySQL provede následující:
SELECT code1 FROM myTable GROUP BY code1 HAVING COUNT(code1) > 1
A uchovávat výsledky v dočasné tabulce (která je hašována, aby bylo vyhledávání rychlejší), pak pro každou hodnotu v myTable
prohledá dočasnou tabulku, aby zjistil, zda tam kód je.
Nicméně, od kdy používáte IN
poddotaz není materializovaný a je přepsán jako:
SELECT t1.code1, t1.code2
FROM myTable t1
WHERE EXISTS
( SELECT t2.code1
FROM myTable t2
WHERE t2.Code1 = t1.Code1
GROUP BY t2.code1
HAVING COUNT(t2.code1) > 1
)
Což znamená, že pro každý code
v myTable
, spustí poddotaz znovu. Což, když je váš vnější dotaz velmi úzký, je v pořádku, protože je efektivnější spustit poddotaz pouze několikrát, než jej spustit pro všechny hodnoty a uložit výsledky do dočasné tabulky, ale když je váš vnější dotaz široký, výsledkem je ve vnitřním dotazu, který se spouští mnohokrát, a zde se projevuje rozdíl ve výkonu.
Takže pokud jde o počty řádků, místo toho, abyste spustili poddotaz ~30 000krát, spustíte jej jednou a poté vyhledáte ~30 000 řádků v hašované dočasné tabulce s pouze 400 řádky. To by představovalo tak drastický rozdíl ve výkonu.
Tento článek v online dokumentech vysvětluje optimalizaci poddotazů mnohem hlouběji.