EXPLAIN
Sintassi
EXPLAIN nome_tab
Oppure:
EXPLAIN [EXTENDED | PARTITIONS] SELECT opzioni_select
Spiegazione
L'istruzione EXPLAIN
può essere utilizzata come sinonimo di
DESCRIBE
oppure per ottenere informazioni sul modo in cui MariaDB
esegue un'istruzione SELECT
:
'EXPLAIN nome_tab'
è sinonimo di
'DESCRIBE nome_tab'
o
'SHOW COLUMNS FROM nome_tab'
.
- Quando la parola chiave
EXPLAIN
precede una istruzione
SELECT
, MariaDB mostra informazioni sul piano di esecuzione della
query, ottenute dall'ottimizzatore. In pratica, MariaDB spiega come intende eseguire
la SELECT
, compreso il modo e l'ordine in cui intende concatenare
le tabelle. EXPLAIN EXTENDED
serve a fornire maggiori
informazioni.
Per ulteriori informazioni su come usare EXPLAIN e EXPLAIN EXTENDED per conoscere
i piani di esecuzione delle query, si veda http://dev.mysql.com/doc/refman/5.1/en/using-explain.html.
EXPLAIN PARTITIONS
è supportato a partire da MySQL 5.1.5. Serve solo quando si esaminano le query che coinvolgono le tabelle
partizionate.
Per i dettagli, si veda
http://dev.mysql.com/doc/refman/5.1/en/partitioning-info.html.
E' disponibile online un EXPLAIN Analyzer che può essere
utilizzato per condividere con altre persone gli output di EXPLAIN
e EXPLAIN
EXTENDED.
The columns in EXPLAIN ... SELECT
Nome Colonna | Spiegazione |
---|---|
id | Numero di sequenza che indica in quale ordine vengono concatenate le tabelle. |
select_type | Da che tipo di SELECT viene la tabella. |
table | Alias dei nomi di tabella. Tabelle temporanee materializzate per le subquery chiamate <subquery#> |
type | In che modo le righe vengono lette (tipo di join). |
possible_keys | keys in table that could be used to find rows in the table |
key | The name of the key that is used to retrieve rows. NULL is no |
key was used.|
key_len | How many bytes of the key that was used (shows if we are using |
only parts of the multi-column key).|
ref | The reference that is used to as the key value. |
rows | An estimate of how many rows we will find in the table for |
each key lookup.|
Extra | Extra information about this join. |
Here are descriptions of the values for some of the more complex columns in
EXPLAIN ... SELECT
:
"select_type" column
The select_type
column can have the following values:
Value | Description |
---|---|
PRIMARY | The SELECT is a PRIMARY one. |
SIMPLE | The SELECT is a SIMPLE one. |
DERIVED | The SELECT is DERIVED from the PRIMARY. |
SUBQUERY | The SELECT is a SUBQUERY of the PRIMARY. |
DEPENDENT SUBQUERY | The SUBQUERY is DEPENDENT. |
UNCACHEABLE SUBQUERY | The SUBQUERY is UNCACHEABLE. |
UNION | The SELECT is a UNION of the PRIMARY. |
UNION RESULT | The result of the UNION. |
DEPENDENT UNION | The UNION is DEPENDENT. |
UNCACHEABLE UNION | The UNION is UNCACHEABLE. |
"Type" column
This column contains information on how the table is accessed.
Value | Description |
---|---|
ALL | A full table scan is done for the table (all rows are |
read). This is bad if the table is large and the table is joined against a previous
table! This happens when the optimizer could not find any usable index to access
rows.
const | There is only one possibly matching row in the table. The |
row is read before the optimization phase and all columns in the table are treated
as constants.
eq_ref | A unique index is used to find the rows. This is the best |
possible plan to find the row.
fulltext | A fulltext index is used to access the rows. |
index_merge | A 'range' access is done for for several index and the |
found rows are merged. The key column shows which keys are used.
index_subquery | This is similar as ref, but used for sub queries that are |
transformed to key lookups.
index | A full scan over the used index. Better than ALL but |
still bad if index is large and the table is joined against a previous table.
range | The table will be accessed with a key over one or more |
value ranges.
ref_or_null | Like 'ref' but in addition another search for the 'null' |
value is done if the first value was not found. This happens usually with sub
queries.
ref | A non unique index or prefix of an unique index is used to |
find the rows. Good if the prefix doesn't match many rows.
system | The table has 0 or 1 rows. |
unique_subquery | This is similar as eq_ref, but used for sub queries that |
are transformed to key lookups
"Extra" column
This column consists of one or more of the following values, separated by ';'
Note that some of these values are detected after the optimization phase.
The optimization phase can do the following changes to the WHERE
clause:
- Add the expressions from the
ON
andUSING
clauses to theWHERE
clause. - Constant propagation: If there is
column=constant
, replace all column instances with this constant. - Replace all columns from '
const
' tables with their values. - Remove the used key columns from the
WHERE
(as this will be tested as part of the key lookup). - Remove impossible constant sub expressions.
For example
WHERE '(a=1 and a=2) OR b=1'
becomes'b=1'
. - Replace columns with other columns that has identical values:
Example:
WHERE
a=b
anda=c
may be treated as'WHERE a=b and a=c and b=c'
. - Add extra conditions to detect impossible row conditions earlier. This
happens mainly with
OUTER JOIN
where we in some cases add detection ofNULL
values in theWHERE
(Part of 'Not exists
' optimization). This can cause an unexpected 'Using where
' in the Extra column. - For each table level we remove expressions that have already been tested when
we read the previous row. Example: When joining tables
t1
witht2
using the followingWHERE 't1.a=1 and t1.a=t2.b'
, we don't have to test't1.a=1'
when checking rows int2
as we already know that this expression is true.
Value | Description |
---|---|
const row not found | The table was a system table (a table with should exactly |
one row), but no row was found.
Distinct | If distinct optimization (remove duplicates) was used. This is marked |
only for the last table in the SELECT.
Full scan on NULL key | The table is a part of the sub query and if the value |
that is used to match the sub query will be NULL, we will do a full table scan.
Impossible HAVING | The used HAVING clause is always false so the SELECT will |
return no rows.
Impossible WHERE noticed after reading const tables. | The |
used WHERE clause is always false so the SELECT will return no rows. This case was
detected after we had read all 'const' tables and used the column values as constant
in the WHERE clause. For example: WHERE const_column=5 and const_column had a value
of 4.
Impossible WHERE | The used WHERE clause is always false so the SELECT will |
return no rows. For example: WHERE 1=2
No matching min/max row | During early optimization of MIN()/MAX() values it was |
detected that no row could match the WHERE clause. The MIN()/MAX() function will
return NULL.
no matching row in const table | The table was a const table (a |
table with only one possible matching row), but no row was found.
No tables used | The SELECT was a sub query that did not use any tables. For |
example a there was no FROM clause or a FROM DUAL clause.
Not exists | Stop searching after more row if we find one single matching row. |
This optimization is used with LEFT JOIN where one is explicitly searching for rows
that doesn't exists in the LEFT JOIN TABLE. Example: SELECT * FROM t1 LEFT JOIN t2
on (...) WHERE t2.not_null_column IS NULL. As t2.not_null_column can only be NULL
if there was no matching row for on condition, we can stop searching if we find a
single matching row.
Open_frm_only | For INFORMATION_SCHEMA tables. Only the frm (table definition |
file was opened) was opened for each matching row.
Open_full_table | For INFORMATION_SCHEMA tables. A full table open for each |
matching row is done to retrieve the requested information. (Slow)
Open_trigger_only | For INFORMATION_SCHEMA tables. Only the trigger file |
definition was opened for each matching row.
Range checked for each record (index map: ...) | This only |
happens when there was no good default index to use but there may some index that
could be used when we can treat all columns from previous table as constants. For
each row combination the optimizer will decide which index to use (if any) to fetch
a row from this table. This is not fast, but faster than a full table scan that is
the only other choice. The index map is a bitmask that shows which index are
considered for each row condition.
Scanned 0/1/all databases | For INFORMATION_SCHEMA tables. Shows how many times |
we had to do a directory scan.
Select tables optimized away | All tables in the join was optimized |
away. This happens when we are only using COUNT(*), MIN() and MAX() functions in the
SELECT and we where able to replace all of these with constants.
Skip_open_table | For INFORMATION_SCHEMA tables. The queried table didn't need |
to be opened.
unique row not found | The table was detected to be a const table (a table with |
only one possible matching row) during the early optimization phase, but no row was
found.
Using filesort | Filesort is needed to resolve the query. This means an extra |
phase where we first collect all columns to sort, sort them with a disk based merge
sort and then use the sorted set to retrieve the rows in sorted order. If there
columns set is small, we store all the columns in the sort file to not have to go to
the database to retrieve them again.
Using index | Only the index is used to retrieve the needed information from the |
table. There is no need to perform an extra seek to retrieve the actual record.
Using index condition | Like 'Using where' but the where condition is pushed |
down to the table engine for internal optimization at the index level.
Using index condition(BKA) | Like 'Using index condition' but in addition we use |
batch key access to retrieve rows.
Using index for group-by | The index is being used to resolve a GROUP BY or |
DISTINCT query. The rows are not read. This is very efficient if the table has a
lot of identical index entries as duplicates are quickly jumped over.
Using intersect(...) | For index_merge joins. Shows which index are part of the |
intersect.
Using join buffer | We store previous row combinations in a row buffer to be |
able to match each row against all of the rows combinations in the join buffer at
one go.
Using sort_union(...) | For index_merge joins. Shows which index are part of the |
union.
Using temporary | A temporary table is created to hold the result. This |
typically happens if you are using GROUP BY, DISTINCT or ORDER BY.
Using where | A WHERE expression (in additional to the possible key lookup) is |
used to check if the row should be accepted. If you don't have 'Using where'
together with a join type of ALL, you are probably doing something wrong!
Using where with pushed condition | Like 'Using where' but the where |
condition is pushed down to the table engine for internal optimization at the row
level.
Examples
Example of ref_or_null
optimization:
SELECT * FROM table_name WHERE key_column=expr OR key_column IS NULL;
ref_or_null
is something that often happens when you use
subqueries with NOT IN
as then one has to do an extra check for
NULL values if the first value didn't have a matching row.