Příkaz EXPLAIN je nástroj pro analýzu dotazů. S jeho pomocí lze získat informace, jakým způsobem je konkrétní dotaz zpracován.
Spuštění je jednoduché ‐ stačí přidat klíčové slovo EXPLAIN
před dotaz.
Výsledkem je, že MySQL vrátí informace o zpracovaném dotazu, namísto aby jej skutečně provedl.
Od MySQL 5.6.3 lze EXPLAIN
spustit pro SELECT
, DELETE
, INSERT
, REPLACE
a UPDATE
.
Ve starších verzích jej lze spusti pouze pro SELECT
.
EXPLAIN SELECT u.jmeno, o.nazev, uk.jmeno AS kamarad FROM uzivatele AS u LEFT JOIN uzivatele AS uk ON uk.id = u.nejlepsi_kamarad_id JOIN obce AS o ON o.id = u.obec_id WHERE u.pohlavi = 'muz' ORDER BY u.datum_narozeni
SQL 1 - Ukázka příkazu EXPLAIN
Výstupem je tabulka s neměnným počtem sloupců a variabilním počtem řádků.
id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
---|---|---|---|---|---|---|---|---|---|
1 | SIMPLE | u | ref | pohlavi_datum_narozeni | pohlavi_datum_narozeni | 1 | const | 1683 | Using index condition; Using where; |
1 | SIMPLE | o | eq_ref | PRIMARY | PRIMARY | 3 | obec_id | 1 | |
1 | SIMPLE | uk | eq_ref | PRIMARY | PRIMARY | 3 | nejlepsi_kamarad_id | 1 | Using where; |
Tabulka 1 - Ukázka výstupu příkazu EXPLAIN
Jak můžete vidět v tabulce 1, jedna tabulka v dotazu odpovídá jednomu řádku ve výstupu.
Všiměte si, že se tabulka uzivatele
objevila ve výstupu vícekrát, jelikož se k ní přistupuje dvakrát.
Později uvidíte, že jako samostatné tabulky zahrnuje MySQL do výstupu i subdotazy či dočasné tabulky.
Pořadí řádků je určeno posloupností v jakém MySQL zpracovává jednotlivé části dotazu. To nemusí vždy korespondovat s pořadím v samotném SQL dotazu, viz. pořadí tabulek v SQL 1 a pořadí řádků v tabulce 1.
Mějte na paměti že výsledky nemusí být vždy přesné a úplné.
Některé statistické výpočty jsou pouze přibližné odhady,
zároveň EXPLAIN
neuvádí veškeré informace, např. o triggerech apod.
Jedná se o číslo, které identifikuje jednotlivé SELECT
y v dotazu.
Číslování je posloupné podle pozice v dotazu, tzn. čím dříve se objeví SELECT
v dotazu, tím menší má id
.
V prvním příkladu byly všechny řádky označeny jako id
1,
jelikož se v dotazu vyskytoval jediný SELECT
.
V dalším příkladě níže je již druhý SELECT
v subdotazu označen jako id
2.
EXPLAIN SELECT u.jmeno, o.nazev, ( SELECT 1 FROM staty LIMIT 1 ) AS const FROM uzivatele AS u JOIN obce AS o ON o.id = u.obec_id WHERE u.pohlavi = 'muz' ORDER BY u.datum_narozeni
SQL 2 - Druhý SELECT
v dotazu
id | select_type | table | ... |
---|---|---|---|
1 | PRIMARY | u | ... |
1 | PRIMARY | o | ... |
2 | SUBQUERY | staty | ... |
Tabulka 2 - Tabulky uzivatele
a obce
jsou označeny s id
1
, jelikož se k nim přistupuje v rámci prvního SELECT
u v dotazu.
Subdotaz označený jako const
se vyskytuje v dotazu až jako druhý, je proto označen jako id
2
.
Jak už název naznačuje, tento sloupec označuje typ SELECT
u.
Může nabývat následujících hodnot:
Jednoduchý SELECT
. V dotazu se nevyskytuje žádný subdotaz či UNION
.
Označení pro první, nejkrajněší SELECT
, v připadě, že se v dotazu vyskytuje subdotaz či UNION
.
Subdotaz v klauzuli SELECT
.
Subdotaz v klauzuli FROM
.
Tento typ subdotazu ukládá MySQL do dočacné tabulky.
Druhý a další posloupný SELECT
v UNION
u.
Výsledek UNION
u.
Jedná se o dočasnou anonymní tabulku s výsledky ze všech SELECT
ů v UNION
u.
Jelikož se v dotazu nevyskytuje žádný SELECT
do této tabulky,
je id
UNION RESULT
u NULL
.
Jako DEPENDENT
mohou být označeny SUBQUERY
a UNION
.
Jedná se o SELECT
y, které závisejí na datech z vnějšího dotazu.
Také jako UNCACHEABLE
mohou být označeny pouze SUBQUERY
a UNION
.
UNCACHEABLE
označuje dotaz jehož výsledek nemůže být cachován.
Hodnota tohoto sloupce je obvykle jednoznačná. Je to název či alias tabulky, ke které se přistupuje.
Výjímku tvoří pouze přístup k anonymním dočasným tabulkám,
které jsou výsledkem SELECT
u typu DERIVED
či UNION
.
Přistupuje-li se k dočasné tabulce vzniklé ze SELECT
u typu DERIVED
,
objeví se jako hodnota tohoto sloupce ve formě <derivedN>
,
kde N je id
DERIVED
SELECT
u.
EXPLAIN SELECT u.jmeno, o.nazev FROM uzivatele AS u JOIN ( SELECT * FROM obce WHERE stat_id > 10 LIMIT 5 ) AS o ON o.id = u.obec_id WHERE u.pohlavi = 'muz' ORDER BY u.datum_narozeni
SQL 3 - Dotaz se subdotazem v klauzily FROM
id | select_type | table | ... |
---|---|---|---|
1 | PRIMARY | u | ... |
1 | PRIMARY | <derived2> | ... |
2 | DERIVED | obce | ... |
Tabulka 3 - JOIN
uje se tabulka vzniklá ze subdotazu, proto se na druhém řádku jako hodnota table objevuje <derived2>
. 2
odkazuje k id
SELECTU
, jehož výsledkem tato anonymní dočasná tabulka vznikla.
V případě dočasné tabulky vzniklé jako výsledek UNION
u, označené jako UNION RESULT
,
se jako hodnota tohoto sloupce objeví <unionN,M>
.
Kde N a M jsou id
jednotlivých SELECT
ů v UNION
u.
EXPLAIN SELECT u.jmeno, u.prijmeni, u.email FROM uzivatele AS u WHERE u.pohlavi = 'muz' AND u.datum_narozeni > '1990-01-01' UNION SELECT u.jmeno, u.prijmeni, u.email FROM uzivatele AS u WHERE u.pohlavi = 'muz' AND u.datum_narozeni < '1990-01-01'
SQL 4 - Dotaz s UNION
em
id | select_type | table | ... |
---|---|---|---|
1 | PRIMARY | u | ... |
2 | UNION | u2 | ... |
NULL | UNION RESULT | <union1,2> | ... |
Tabulka 4 - V UNION
u jsou dva SELECT
y, ve výstupu označené jako 1
a 2
. Výsledky obou SELECT
ů MySQL uloží do dočasné tabulky, ta se objevuje jako třetí řádek ve výstupu. Jelikož se k ní nepřistupuje žádným SELECT
em, je hodnota id
NULL
. <union1,2>
jako hodnota table odkazuje na SELECT
y ze kterých výsledek vznikl (SELECT
id
1
a 2
).
Tento sloupec může nabývat několika definovaných hodnot. Udávájí jakým způsobem MySQL přistupuje do tabulky.
Table scan. MySQL musí projít celou tabulku, od prvního řádku až k poslednímu.
Totéž co ALL
, s tím rozdílem že MySQL přistupuje k řádkům tabulky v pořadí podle indexu.
Jde tedy o získání všech řádků seřazených podle indexu.
MySQL přistupuje do tabulky podle indexu pouze v určitém rozsahu. Obvykle jde o filtrování indexovaného sloupce operátory >
, <
, BETWEEN
, apod.
Jde o porovnání neunikátního indexu s jednou hodnotou. Opět tedy musí MySQL přistoupit k více řádkům tabulky, nicméně oproti range
se již index neporovnává vůči rozsahu hodnot, nýbrž vůči jedné hodnotě.
MySQL porovnává při JOIN
ování unikátní index s jednou určitou hodnotou.
Nejlepší možný způsob přístupu do tabulky. Podobně jako u eq_ref
je výstupem nanejvíš jeden řádek.
MySQL vůbec do tabulky nepřistupuje. Výsledek dotazu je známý již ve fázi optimalizace.
Jde o indexy, které MySQL vyhodnotilo jako užitečné pro zeefektivnění přístupu do tabulky.
Sloupec s názvem indexu, který byl pro dotaz využit.
Použitý index nemusí vždy korespondovat se seznamem v possible_keys
. Prakticky to velmi často znamená, že je ve snaze co nejvíce zvýšit efektivitu dotazu využit tzv. covering index, který sice nemusí pomoci účelně nalézt požadované řádky, nicméně výrazně urychluje jejich získání.
Velikost použitého indexu v bajtech.
Obsahem jsou názvy sloupců odkazující tabulky, které byly využity pro porovnání s použitým indexem.
EXPLAIN SELECT u.jmeno, u.prijmeni, u.email FROM uzivatele AS u WHERE u.pohlavi = 'muz' AND u.datum_narozeni = '1990-01-01'
SQL 5 - Ukázka filtrování v dotazu dvěma konstantami
... | possible_keys | key | key_len | ref | ... |
---|---|---|---|---|---|
... | pohlavi_datum_narozeni | pohlavi_datum_narozeni | 4 | const,const | ... |
Tabulka 5 - V případě, že se index porovnává s konstantami (nikoliv s hodnotami z jiných tabulek), objeví se v ref
hodnota const
.
Odhad počtu řádků tabulky, které bude nutno přečíst k nalezení všech požadovaných řádků.
EXPLAIN SELECT * FROM `uzivatele` WHERE 1 LIMIT 10
SQL 6 - Dotaz s LIMIT
em
... | rows | ... |
---|---|---|
... | 5006 | ... |
Tabulka 6 - rows
je nejnepřesnější sloupec EXPLAIN
u. V tomto případě je hodnota rows
5006, ačkoliv MySQL přečte díky LIMIT
u pouze 10 řádku.
Sloupec Extra
obsahuje některé dodatečné informace.
Seznam a popis všech možných hodnot naleznete v manuálu.