sql >> Databáze >  >> RDS >> Mysql

JOIN vs. WHERE:Proč dva dotazy, které získají identické výsledky, vykazují 3–4 řádové rozdíly ve výkonu?

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.




  1. 4 tipy pro spuštění diagnostiky serveru SQL

  2. Oprava:„Příkaz BACKUP LOG není povolen, když je model obnovy JEDNODUCHÝ“ v SQL Server (a SQL Edge)

  3. SQL Injection a klauzule LIMIT

  4. Získejte čas a čas pomocí T-SQL?