SQL Order of Operations – V jakém pořadí MySQL provádí dotazy?
Klikněte pro spuštění, zdarma.
Znalost bitů a bajtů pořadí operací dotazu SQL může být velmi cenná, protože může usnadnit proces psaní nových dotazů a zároveň je velmi přínosná při snaze o optimalizaci dotazu SQL.
Pokud hledáte zkrácenou verzi, jedná se o logické pořadí operací, známé také jako pořadí provádění, pro dotaz SQL:
- OD, včetně funkcí JOIN
- WHERE
- GROUP BY
- HAVING
- WINDOW
- SELECT
- DISTINCT
- UNION
- ORDER BY
- LIMIT a OFFSET
.
Ale skutečnost není tak jednoduchá ani přímočará. Jak jsme si řekli, standard SQL definuje pořadí provádění jednotlivých klauzulí dotazu SQL. Jak již bylo řečeno, moderní databáze již toto výchozí pořadí zpochybňují použitím některých optimalizačních triků, které mohou změnit skutečné pořadí provádění, ačkoli nakonec musí vrátit stejný výsledek, jako kdyby prováděly dotaz ve výchozím pořadí provádění.
Proč by to dělaly? No, může to být hloupost, pokud by databáze nejprve načetla všechna data uvedená v klauzuli FROM (včetně JOINů) a teprve potom by se podívala do klauzule WHERE a jejích indexů. Tyto tabulky mohou obsahovat spoustu dat, takže si dokážete představit, co by se stalo, kdyby se optimalizátor databáze držel tradičního pořadí operací dotazu SQL.
Podívejme se na jednotlivé části dotazu SQL podle pořadí jejich provádění.
FROM a JOINy
Tabulky uvedené v klauzuli FROM (včetně JOINů) se vyhodnotí jako první, aby se určila celá pracovní množina, která je pro dotaz relevantní. Databáze sloučí data ze všech tabulek podle klauzulí JOINs ON a zároveň načte data z poddotazů a může dokonce vytvořit některé dočasné tabulky pro uložení dat vrácených z poddotazů v této klauzuli.
V mnoha případech se však optimalizátor databáze rozhodne vyhodnotit nejprve část WHERE, aby zjistil, kterou část pracovní množiny lze vynechat (nejlépe pomocí indexů), takže nebude příliš nafukovat množinu dat, pokud to není opravdu nutné.
Kde je klauzule
Kde je klauzule bude vyhodnocena jako druhá po klauzuli FROM. Máme k dispozici pracovní soubor dat a nyní můžeme filtrovat data podle podmínek v klauzuli WHERE.
Tyto podmínky mohou obsahovat odkazy na data a tabulky z klauzule FROM, ale nemohou obsahovat žádné odkazy na aliasy definované v klauzuli SELECT, protože tato data a tyto aliasy ještě nemusí v tomto kontextu „existovat“, protože tato klauzule ještě nebyla databází vyhodnocena.
Obvyklým úskalím klauzule WHERE je také snaha odfiltrovat agregované hodnoty v klauzuli WHERE, například pomocí této klauzule: „WHERE sum(available_stock) > 0“. Tento příkaz způsobí neúspěšné provedení dotazu, protože agregace budou vyhodnoceny později v procesu (viz část GROUP BY níže). Chcete-li použít podmínku filtrování na agregovaná data, měli byste použít klauzuli HAVING, a nikoli klauzuli WHERE.
Klauzule GROUP BY
Nyní, když jsme vyfiltrovali soubor dat pomocí klauzule WHERE, můžeme data agregovat podle jednoho nebo více sloupců, které se objevují v klauzuli GROUP BY. Seskupení dat je vlastně jejich rozdělení na různé části nebo kbelíky, kde každý kbelík má jeden klíč a seznam řádků, které tomuto klíči odpovídají. Nemít klauzuli GROUP BY je jako dát všechny řádky do jednoho obrovského kbelíku.
Po agregaci dat můžete nyní použít agregační funkce, které vrátí hodnotu pro každou skupinu pro každý z kbelíků. Mezi takové agregační funkce patří COUNT, MIN, MAX, SUM a další.
Doložka HAVING
Když jsme nyní seskupili data pomocí doložky GROUP BY, můžeme použít doložku HAVING k vyfiltrování některých kyblíků. Podmínky v klauzuli HAVING mohou odkazovat na agregační funkce, takže příklad, který nefungoval v klauzuli WHERE výše, bude bez problémů fungovat v klauzuli HAVING: „HAVING sum(available_stock) > 0“.
Jelikož jsme již data seskupili, nemůžeme již v tomto okamžiku přistupovat k původním řádkům, takže můžeme použít pouze podmínky pro filtrování celých kbelíků, nikoliv jednotlivých řádků v kbelíku.
Jak jsme se již zmínili v předchozích částech, ani v tomto oddíle nelze přistupovat k aliasům definovaným v klauzuli SELECT, protože je databáze ještě nevyhodnotila (to platí ve většině databází).
Funkce Window
Používáte-li funkce Window, v tomto bodě se provedou. Stejně jako mechanismus seskupování i funkce Window provádějí výpočet nad sadou řádků. Hlavní rozdíl je v tom, že při použití funkcí Window si každý řádek zachová svou vlastní identitu a nebude seskupen do kbelíku dalších podobných řádků.
Funkce Window lze použít pouze v klauzuli SELECT nebo ORDER BY. Agregační funkce můžete použít uvnitř okenních funkcí, například:
SUM(COUNT(*)) OVER ()
Klausule SELECT
Teď, když jsme skončili s vyřazováním řádků ze souboru dat a seskupováním dat, můžeme vybrat data, která chceme z dotazu načíst na stranu klienta. Uvnitř klauzule SELECT můžete používat názvy sloupců, agregace a poddotazy. Mějte na paměti, že pokud v klauzuli SELECT používáte odkaz na agregační funkci, například COUNT(*), jedná se pouze o odkaz na agregaci, která již proběhla při seskupování, takže samotná agregace v klauzuli SELECT neprobíhá, ale jedná se pouze o odkaz na její výslednou množinu.
Klíčové slovo DISTINCT
Syntaxe klíčového slova DISTINCT je trochu matoucí, protože klíčové slovo zaujímá své místo před názvy sloupců v klauzuli SELECT. Skutečná operace DISTINCT však probíhá až za klauzulí SELECT. Při použití klíčového slova DISTINCT databáze vyřadí řádky s duplicitními hodnotami ze zbývajících řádků, které zbyly po provedeném filtrování a agregaci.
Klíčové slovo UNION
Klíčové slovo UNION spojuje výsledkové množiny dvou dotazů do jedné výsledkové množiny. Většina databází umožňuje volbu mezi UNION DISTINCT (který ze sloučené množiny výsledků vyřadí duplicitní řádky) nebo UNION ALL (který pouze sloučí množiny výsledků bez použití kontroly duplicity).
Na množinu výsledků UNION můžete aplikovat třídění (ORDER BY) a omezení (LIMIT) stejně jako na běžný dotaz.
DoložkaORDER BY
Třídění probíhá, jakmile má databáze připravenou celou množinu výsledků (po filtrování, seskupení, odstranění duplicit). Jakmile ji máme, může nyní databáze setřídit množinu výsledků pomocí sloupců, vybraných aliasů nebo agregačních funkcí, i když nejsou součástí vybraných dat. Jedinou výjimkou je použití klíčového slova DISTINCT, které znemožňuje seřazení podle nevybraného sloupce, protože v takovém případě bude pořadí výsledné sady nedefinované.
Můžete si vybrat, zda chcete data seřadit pomocí sestupného (DESC) nebo vzestupného (ASC) pořadí. Pořadí může být pro každou z částí řazení jedinečné, takže platí následující: ORDER BY firstname ASC, age DESC
LIMIT a OFFSET
Ve většině případů použití (s výjimkou několika málo případů, jako je vykazování) bychom chtěli vyřadit všechny řádky kromě prvních X řádků výsledku dotazu. Klauzule LIMIT, která se provede po seřazení, nám právě toto umožňuje. Kromě toho lze pomocí kombinace klíčových slov LIMIT a OFFSET zvolit, od kterého řádku se mají data začít načítat a kolik jich má být vyloučeno. Následující příklad načte 50 řádků počínaje řádkem č. 100: LIMIT 50 OFFSET 100
Klikněte pro spuštění, zdarma.