MySQL explain query 结果域值含义
2013-12-26 21:32
417 查看
see: http://dev.mysql.com/doc/refman/5.0/en/explain-output.html#explain-join-types
The
provides information about the execution plan for a
a row of information for each table used in the
It lists the tables in the output in the order that MySQL would read them while processing the statement. MySQL resolves all joins using a nested-loop join method. This means that MySQL reads a row from the first table, and then finds a matching row in the
second table, the third table, and so on. When all tables are processed, MySQL outputs the selected columns and backtracks through the table list until a table is found for which there are more matching rows. The next row is read from this table and the process
continues with the next table.
When the
extra information that can be viewed by issuing a
See Section 8.2.3,
“
Columns
Types
Information
Interpretation
This section describes the output columns produced by
Later sections provide additional information about the
Each output row from
information about one table. Each row contains the values summarized inTable 8.1,
“
in more detail following the table.
Table 8.1.
Columns
The
This is the sequential number of the
the query. The value can be
row refers to the union result of other rows. In this case, the
shows a value like
indicate that the row refers to the union of the rows with
of
The type of
which can be any of those shown in the following table.
a correlated subquery. See Section 13.2.9.7,
“Correlated Subqueries”.
the subquery is re-evaluated only once for each set of different values of the variables from its outer context. For
Cacheability of subqueries differs from caching of query results in the query cache (which is described inSection 8.6.3.1,
“How the Query Cache Operates”). Subquery caching occurs during query execution, whereas the query cache is used to store results only after query execution finishes.
The name of the table to which the row of output refers. This can also be one of the following values:
The row refers to the union of the rows with
of
The row refers to the derived table result for the row with an
of
A derived table may result, for example, from a subquery in the
The join type. For descriptions of the different types, see
Types.
The
indexes MySQL can choose from use to find the rows in this table. Note that this column is totally independent of the order of the tables as displayed in the output from
That means that some of the keys in
not be usable in practice with the generated table order.
If this column is
indexes. In this case, you may be able to improve the performance of your query by examining the
to check whether it refers to some column or columns that would be suitable for indexing. If so, create an appropriate index and check the query with
SeeSection 13.1.4,
“
To see what indexes a table has, use
The
that MySQL actually decided to use. If MySQL decides to use one of the
to look up rows, that index is listed as the key value.
It is possible that
that is not present in the
This can happen if none of the
are suitable for looking up rows, but all the columns selected by the query are columns of some other index. That is, the named index covers the selected columns, so although it is not used to determine which rows to retrieve, an index scan is more efficient
than a data row scan.
For
the selected columns even if the query also selects the primary key because
the primary key value with each secondary index. If
MySQL found no index to use for executing the query more efficiently.
To force MySQL to use or ignore an index listed in the
use
query. See Section 13.2.8.3,
“Index Hint Syntax”.
For
and
--analyze does the same as
“
The
of the key that MySQL decided to use. The length is
the
Note that the value of
you to determine how many parts of a multiple-part key MySQL actually uses.
The
are compared to the index named in the
to select rows from the table.
The
rows MySQL believes it must examine to execute the query.
For
this number is an estimate, and may not always be exact.
This column contains additional information about how MySQL resolves the query. For descriptions of the different values, see
Information.
The
describes how tables are joined. The following list describes the join types, ordered from the best type to the worst:
The table has only one row (= system table). This is a special case of the
type.
The table has at most one matching row, which is read at the start of the query. Because there is only one row, values from the column in this row can be regarded as constants by the rest of the optimizer.
are very fast because they are read only once.
used when you compare all parts of a
values. In the following queries,
be used as a
SELECT * FROM
WHERE
[/code]
One row is read from this table for each combination of rows from the previous tables. Other than the
this is the best possible join type. It is used when all parts of an index are used by the join and the index is a
be used for indexed columns that are compared using the
The comparison value can be a constant or an expression that uses columns from tables that are read before this table. In the following examples, MySQL can use an
to process
WHERE
SELECT * FROM
WHERE
AND
[/code]
All rows with matching index values are read from this table for each combination of rows from the previous tables.
used if the join uses only a leftmost prefix of the key or if the key is not a
if the join cannot select a single row based on the key value). If the key that is used matches only a few rows, this is a good join type.
be used for indexed columns that are compared using the
In the following examples, MySQL can use a
to process
SELECT * FROM
WHERE
SELECT * FROM
WHERE
AND
[/code]
The join is performed using a
This join type is like
but with the addition that MySQL does an extra search for rows that contain
This join type optimization is used most often in resolving subqueries. In the following examples, MySQL can use a
to process
WHERE
[/code]
See Section 8.3.1.6,
“
This join type indicates that the Index Merge optimization is used. In this case, the
in the output row contains a list of indexes used, and
a list of the longest key parts for the indexes used. For more information, see Section 8.3.1.4,
“Index Merge Optimization”.
This type replaces
some
[/code]
just an index lookup function that replaces the subquery completely for better efficiency.
This join type is similar to
It replaces
for nonunique indexes in subqueries of the following form:
[/code]
Only rows that are in a given range are retrieved, using an index to select the rows. The
in the output row indicates which index is used. The
the longest key part that was used. The
is
be used when a key column is compared to a constant using any of the
or
WHERE
SELECT * FROM
WHERE
SELECT * FROM
WHERE
SELECT * FROM
WHERE
[/code]
The
except that the index tree is scanned. This occurs two ways:
If the index is a covering index for the queries and can be used to satisify all data required from the table, only the index tree is scanned. In this case, the
says
is faster than
the index usually is smaller than the table data.
A full table scan is performed using reads from the index to look up data rows in index order.
MySQL can use this join type when the query uses only columns that are part of a single index.
A full table scan is done for each combination of rows from the previous tables. This is normally not good if the table is the first table not marked
and usually very bad
in all other cases. Normally, you can avoid
adding indexes that enable row retrieval from the table based on constant values or column values from earlier tables.
The
contains additional information about how MySQL resolves the query. The following list explains the values that can appear in this column. If you want to make your queries as fast as possible, look out for
of
For a query such as
the table was empty.
MySQL is looking for distinct values, so it stops searching for more rows for the current row combination after it has found the first matching row.
This occurs for subquery optimization as a fallback strategy when the optimizer cannot use an index-lookup access method.
The
select any rows.
The
select any rows.
MySQL has read all
tables and notice that the
is always false.
No row satisfies the condition for a query such as
For a query with a join, there was an empty table or a table with no rows satisfying a unique index condition.
The query has no
MySQL was able to do a
on the query and does not examine more rows in this table for the previous row combination after it finds one row that matches the
Assume that
looks up the rows in
of
in
never be
the rest of the rows in
same
row in
lookup in
actually match in
MySQL found no good index to use, but found that some of indexes might be used after column values from preceding tables are known. For each row combination in the preceding tables, MySQL checks whether it is possible to use a
method to retrieve rows. This is not very fast, but is faster than performing a join with no index at all. The applicability criteria are as described in Section 8.3.1.3,
“Range Optimization”, and Section 8.3.1.4,
“Index Merge Optimization”, with the exception that all column values for the preceding table are known and considered to be constants.
Indexes are numbered beginning with 1, in the same order as shown by
a bitmask value that indicates which indexes are candidates. For example, a value of
11001) means that indexes 1, 4, and 5 will be considered.
The query contained only aggregate functions (
that were all resolved using an index, or
and no
determined that only one row should be returned.
For a query such as
no rows satisfy the condition for a
or
MySQL must do an extra pass to find out how to retrieve the rows in sorted order. The sort is done by going through all rows according to the join type and storing the sort key and pointer to the row for all rows that match the
The keys then are sorted and the rows are retrieved in sorted order. See Section 8.3.1.11,
“
The column information is retrieved from the table using only information in the index tree without having to do an additional seek to read the actual row. This strategy can be used when the query uses only columns that are part of a single index.
If the
Similar to the
method,
that MySQL found an index that can be used to retrieve all columns of a
extra disk access to the actual table. Additionally, the index is used in the most efficient way so that for each group, only a few index entries are read. For details, see Section 8.3.1.12,
“
These indicate how index scans are merged for the
type. See Section 8.3.1.4,
“Index Merge Optimization”.
To resolve the query, MySQL needs to create a temporary table to hold the result. This typically happens if the query contains
columns differently.
A
rows to match against the next table or send to the client. Unless you specifically intend to fetch or examine all rows from the table, you may have something wrong in your query if the
is not
type is
Even if you are using an index for all parts of a
you may see
can be
This item applies to
It means that MySQL Cluster is using the Condition Pushdown optimization to improve the efficiency of a direct comparison between a nonindexed column and a constant. In such cases, the condition is “pushed
down” to the cluster's data nodes and is evaluated on all data nodes simultaneously. This eliminates the need to send nonmatching rows over the network, and can speed up such queries by a factor of 5 to 10 times over cases where Condition Pushdown
could be but is not used. For more information, see Section 8.3.1.5,
“Engine Condition Pushdown Optimization”.
You can get a good indication of how good a join is by taking the product of the values in the
of the
This should tell you roughly how many rows MySQL must examine to execute the query. If you restrict queries with the
variable, this row product also is used to determine which multiple-table
to execute and which to abort. See Section 8.9.2,
“Tuning Server Parameters”.
The following example shows how a multiple-table join can be optimized progressively based on the information provided by
Suppose that you have the
shown here and that you plan to examine it using
For this example, make the following assumptions:
The columns being compared have been declared as follows.
The tables have the following indexes.
The
Initially, before any optimizations have been performed, the
produces the following information:
Because
each table, this output indicates that MySQL is generating a Cartesian product of all the tables; that is, every combination of rows. This takes quite a long time, because the product of the number of rows in each table must be examined. For the case at hand,
this product is 74 × 2135 × 74 × 3872 = 45,268,558,720 rows. If the tables were bigger, you can only imagine how long it would take.
One problem here is that MySQL can use indexes on columns more efficiently if they are declared as the same type and size. In this context,
considered the same if they are declared as the same size.
declared as
so there is a length mismatch.
To fix this disparity between column lengths, use
10 characters to 15 characters:
[/code]
Now
both
again produces this result:
This is not perfect, but is much better: The product of the
is less by a factor of 74. This version executes in a couple of seconds.
A second alteration can be made to eliminate the column length mismatches for the
->
[/code]
After that modification,
the output shown here:
At this point, the query is optimized almost as well as possible. The remaining problem is that, by default, MySQL assumes that values in the
are evenly distributed, and that is not the case for the
Fortunately, it is easy to tell MySQL to analyze the key distribution:
[/code]
With the additional index information, the join is perfect and
this result:
Note that the
in the output from
an educated guess from the MySQL join optimizer. You should check whether the numbers are even close to the truth by comparing the
with the actual number of rows that the query returns. If the numbers are quite different, you might get better performance by using
your
and trying to list the tables in a different order in the
It is possible in some cases to execute statements that modify data when
“Subqueries in the
8.2.2. EXPLAIN
Output Format
The EXPLAINstatement
provides information about the execution plan for a
SELECTstatement.
EXPLAINreturns
a row of information for each table used in the
SELECTstatement.
It lists the tables in the output in the order that MySQL would read them while processing the statement. MySQL resolves all joins using a nested-loop join method. This means that MySQL reads a row from the first table, and then finds a matching row in the
second table, the third table, and so on. When all tables are processed, MySQL outputs the selected columns and backtracks through the table list until a table is found for which there are more matching rows. The next row is read from this table and the process
continues with the next table.
When the
EXTENDEDkeyword is used,
EXPLAINproduces
extra information that can be viewed by issuing a
SHOW WARNINGSstatement following the
EXPLAINstatement.
See Section 8.2.3,
“
EXPLAIN EXTENDEDOutput Format”.
EXPLAINOutput
Columns
EXPLAINJoin
Types
EXPLAINExtra
Information
EXPLAINOutput
Interpretation
EXPLAIN
Output
Columns
This section describes the output columns produced by EXPLAIN.
Later sections provide additional information about the
typeand
Extracolumns.
Each output row from
EXPLAINprovides
information about one table. Each row contains the values summarized inTable 8.1,
“
EXPLAINOutput Columns”, and described
in more detail following the table.
Table 8.1.
EXPLAINOutput
Columns
Column | Meaning |
---|---|
id | The SELECTidentifier |
select_type | The SELECTtype |
table | The table for the output row |
type | The join type |
possible_keys | The possible indexes to choose |
key | The index actually chosen |
key_len | The length of the chosen key |
ref | The columns compared to the index |
rows | Estimate of rows to be examined |
Extra | Additional information |
id
The
SELECTidentifier.
This is the sequential number of the
SELECTwithin
the query. The value can be
NULLif the
row refers to the union result of other rows. In this case, the
tablecolumn
shows a value like
<unionM,
N> to
indicate that the row refers to the union of the rows with
idvalues
of
Mand
N.
select_type
The type of
SELECT,
which can be any of those shown in the following table.
select_typeValue | Meaning |
---|---|
SIMPLE | Simple SELECT(not using UNIONor subqueries) |
PRIMARY | Outermost SELECT |
UNION | Second or later SELECTstatement in a UNION |
DEPENDENT UNION | Second or later SELECTstatement in a UNION, dependent on outer query |
UNION RESULT | Result of a UNION. |
SUBQUERY | First SELECTin subquery |
DEPENDENT SUBQUERY | First SELECTin subquery, dependent on outer query |
DERIVED | Derived table SELECT(subquery in FROMclause) |
UNCACHEABLE SUBQUERY | A subquery for which the result cannot be cached and must be re-evaluated for each row of the outer query |
DEPENDENTtypically signifies the use of
a correlated subquery. See Section 13.2.9.7,
“Correlated Subqueries”.
DEPENDENT SUBQUERYevaluation differs from
UNCACHEABLE SUBQUERYevaluation. For
DEPENDENT SUBQUERY,
the subquery is re-evaluated only once for each set of different values of the variables from its outer context. For
UNCACHEABLE SUBQUERY, the subquery is re-evaluated for each row of the outer context.
Cacheability of subqueries differs from caching of query results in the query cache (which is described inSection 8.6.3.1,
“How the Query Cache Operates”). Subquery caching occurs during query execution, whereas the query cache is used to store results only after query execution finishes.
table
The name of the table to which the row of output refers. This can also be one of the following values:
<unionM,
N>:
The row refers to the union of the rows with
idvalues
of
Mand
N.
<derivedN>:
The row refers to the derived table result for the row with an
idvalue
of
N.
A derived table may result, for example, from a subquery in the
FROMclause.
type
The join type. For descriptions of the different types, see
EXPLAINJoin
Types.
possible_keys
The
possible_keyscolumn indicates which
indexes MySQL can choose from use to find the rows in this table. Note that this column is totally independent of the order of the tables as displayed in the output from
EXPLAIN.
That means that some of the keys in
possible_keysmight
not be usable in practice with the generated table order.
If this column is
NULL, there are no relevant
indexes. In this case, you may be able to improve the performance of your query by examining the
WHEREclause
to check whether it refers to some column or columns that would be suitable for indexing. If so, create an appropriate index and check the query with
EXPLAINagain.
SeeSection 13.1.4,
“
ALTER TABLESyntax”.
To see what indexes a table has, use
SHOW INDEX FROM tbl_name.
key
The
keycolumn indicates the key (index)
that MySQL actually decided to use. If MySQL decides to use one of the
possible_keysindexes
to look up rows, that index is listed as the key value.
It is possible that
keywill name an index
that is not present in the
possible_keysvalue.
This can happen if none of the
possible_keysindexes
are suitable for looking up rows, but all the columns selected by the query are columns of some other index. That is, the named index covers the selected columns, so although it is not used to determine which rows to retrieve, an index scan is more efficient
than a data row scan.
For
InnoDB, a secondary index might cover
the selected columns even if the query also selects the primary key because
InnoDBstores
the primary key value with each secondary index. If
keyis
NULL,
MySQL found no index to use for executing the query more efficiently.
To force MySQL to use or ignore an index listed in the
possible_keyscolumn,
use
FORCE INDEX,
USE INDEX, or
IGNORE INDEXin your
query. See Section 13.2.8.3,
“Index Hint Syntax”.
For
MyISAM,
NDB,
and
BDBtables, running
ANALYZE TABLEhelps the optimizer choose better indexes. For
MyISAMtables, myisamchk
--analyze does the same as
ANALYZE TABLE. See Section 7.6,
“
MyISAMTable Maintenance and Crash Recovery”.
key_len
The
key_lencolumn indicates the length
of the key that MySQL decided to use. The length is
NULLif
the
keycolumn says
NULL.
Note that the value of
key_lenenables
you to determine how many parts of a multiple-part key MySQL actually uses.
ref
The
refcolumn shows which columns or constants
are compared to the index named in the
keycolumn
to select rows from the table.
rows
The
rowscolumn indicates the number of
rows MySQL believes it must examine to execute the query.
For
InnoDBtables,
this number is an estimate, and may not always be exact.
Extra
This column contains additional information about how MySQL resolves the query. For descriptions of the different values, see
EXPLAINExtra
Information.
EXPLAIN
Join
Types
The typecolumn of
EXPLAINoutput
describes how tables are joined. The following list describes the join types, ordered from the best type to the worst:
system
The table has only one row (= system table). This is a special case of the
constjoin
type.
const
The table has at most one matching row, which is read at the start of the query. Because there is only one row, values from the column in this row can be regarded as constants by the rest of the optimizer.
consttables
are very fast because they are read only once.
constis
used when you compare all parts of a
PRIMARY KEYor
UNIQUEindex to constant
values. In the following queries,
tbl_namecan
be used as a
consttable:
SELECT * FROM [code]tbl_nameWHERE
primary_key=1;
SELECT * FROM
tbl_name
WHERE
primary_key_part1=1 AND
primary_key_part2=2;
[/code]
eq_ref
One row is read from this table for each combination of rows from the previous tables. Other than the
systemand
consttypes,
this is the best possible join type. It is used when all parts of an index are used by the join and the index is a
PRIMARY KEYor
UNIQUE NOT NULLindex.
eq_refcan
be used for indexed columns that are compared using the
=operator.
The comparison value can be a constant or an expression that uses columns from tables that are read before this table. In the following examples, MySQL can use an
eq_refjoin
to process
ref_table:
SELECT * FROM [code]ref_table,
other_table
WHERE
ref_table.
key_column=
other_table.
column;
SELECT * FROM
ref_table,
other_table
WHERE
ref_table.
key_column_part1=
other_table.
column
AND
ref_table.
key_column_part2=1;
[/code]
ref
All rows with matching index values are read from this table for each combination of rows from the previous tables.
refis
used if the join uses only a leftmost prefix of the key or if the key is not a
PRIMARY KEYor
UNIQUEindex (in other words,
if the join cannot select a single row based on the key value). If the key that is used matches only a few rows, this is a good join type.
refcan
be used for indexed columns that are compared using the
=or
<=>operator.
In the following examples, MySQL can use a
refjoin
to process
ref_table:
SELECT * FROM [code]ref_tableWHERE
key_column=
expr;
SELECT * FROM
ref_table,
other_table
WHERE
ref_table.
key_column=
other_table.
column;
SELECT * FROM
ref_table,
other_table
WHERE
ref_table.
key_column_part1=
other_table.
column
AND
ref_table.
key_column_part2=1;
[/code]
fulltext
The join is performed using a
FULLTEXTindex.
ref_or_null
This join type is like
ref,
but with the addition that MySQL does an extra search for rows that contain
NULLvalues.
This join type optimization is used most often in resolving subqueries. In the following examples, MySQL can use a
ref_or_nulljoin
to process
ref_table:
SELECT * FROM [code]ref_table
WHERE
key_column=
exprOR
key_columnIS NULL;
[/code]
See Section 8.3.1.6,
“
IS NULLOptimization”.
index_merge
This join type indicates that the Index Merge optimization is used. In this case, the
keycolumn
in the output row contains a list of indexes used, and
key_lencontains
a list of the longest key parts for the indexes used. For more information, see Section 8.3.1.4,
“Index Merge Optimization”.
unique_subquery
This type replaces
reffor
some
INsubqueries of the following form:
valueIN (SELECT
primary_keyFROM
single_tableWHERE
some_expr)
[/code]
unique_subqueryis
just an index lookup function that replaces the subquery completely for better efficiency.
index_subquery
This join type is similar to
unique_subquery.
It replaces
INsubqueries, but it works
for nonunique indexes in subqueries of the following form:
valueIN (SELECT
key_columnFROM
single_tableWHERE
some_expr)
[/code]
range
Only rows that are in a given range are retrieved, using an index to select the rows. The
keycolumn
in the output row indicates which index is used. The
key_lencontains
the longest key part that was used. The
refcolumn
is
NULLfor this type.
rangecan
be used when a key column is compared to a constant using any of the
=,
<>,
>,
>=,
<,
<=,
IS NULL,
<=>,
BETWEEN,
or
IN()operators:
SELECT * FROM [code]tbl_name
WHERE
key_column= 10;
SELECT * FROM
tbl_name
WHERE
key_columnBETWEEN 10 and 20;
SELECT * FROM
tbl_name
WHERE
key_columnIN (10,20,30);
SELECT * FROM
tbl_name
WHERE
key_part1= 10 AND
key_part2IN (10,20,30);
[/code]
index
The
indexjoin type is the same as
ALL,
except that the index tree is scanned. This occurs two ways:
If the index is a covering index for the queries and can be used to satisify all data required from the table, only the index tree is scanned. In this case, the
Extracolumn
says
Using index. An index-only scan usually
is faster than
ALLbecause the size of
the index usually is smaller than the table data.
A full table scan is performed using reads from the index to look up data rows in index order.
Uses indexdoes not appear in the
Extracolumn.
MySQL can use this join type when the query uses only columns that are part of a single index.
ALL
A full table scan is done for each combination of rows from the previous tables. This is normally not good if the table is the first table not marked
const,
and usually very bad
in all other cases. Normally, you can avoid
ALLby
adding indexes that enable row retrieval from the table based on constant values or column values from earlier tables.
EXPLAIN
Extra
Information
The Extracolumn of
EXPLAINoutput
contains additional information about how MySQL resolves the query. The following list explains the values that can appear in this column. If you want to make your queries as fast as possible, look out for
Extravalues
of
Using filesortand
Using temporary.
const row not found
For a query such as
SELECT ... FROM tbl_name,
the table was empty.
Distinct
MySQL is looking for distinct values, so it stops searching for more rows for the current row combination after it has found the first matching row.
Full scan on NULL key
This occurs for subquery optimization as a fallback strategy when the optimizer cannot use an index-lookup access method.
Impossible HAVING
The
HAVINGclause is always false and cannot
select any rows.
Impossible WHERE
The
WHEREclause is always false and cannot
select any rows.
Impossible WHERE noticed after reading const tables
MySQL has read all
const(and
system)
tables and notice that the
WHEREclause
is always false.
No matching min/max row
No row satisfies the condition for a query such as
SELECT MIN(...) FROM ... WHERE condition.
no matching row in const table
For a query with a join, there was an empty table or a table with no rows satisfying a unique index condition.
No tables used
The query has no
FROMclause, or has a
FROM DUALclause.
Not exists
MySQL was able to do a
LEFT JOINoptimization
on the query and does not examine more rows in this table for the previous row combination after it finds one row that matches the
LEFT JOINcriteria. Here is an example of the type of query that can be optimized this way:
SELECT * FROM t1 LEFT JOIN t2 ON t1.id=t2.id WHERE t2.id IS NULL;
Assume that
t2.idis defined as
NOT NULL. In this case, MySQL scans
t1and
looks up the rows in
t2using the values
of
t1.id. If MySQL finds a matching row
in
t2, it knows that
t2.idcan
never be
NULL, and does not scan through
the rest of the rows in
t2that have the
same
idvalue. In other words, for each
row in
t1, MySQL needs to do only a single
lookup in
t2, regardless of how many rows
actually match in
t2.
Range checked for each record (index map: N)
MySQL found no good index to use, but found that some of indexes might be used after column values from preceding tables are known. For each row combination in the preceding tables, MySQL checks whether it is possible to use a
rangeor
index_mergeaccess
method to retrieve rows. This is not very fast, but is faster than performing a join with no index at all. The applicability criteria are as described in Section 8.3.1.3,
“Range Optimization”, and Section 8.3.1.4,
“Index Merge Optimization”, with the exception that all column values for the preceding table are known and considered to be constants.
Indexes are numbered beginning with 1, in the same order as shown by
SHOW INDEXfor the table. The index map value
Nis
a bitmask value that indicates which indexes are candidates. For example, a value of
0x19(binary
11001) means that indexes 1, 4, and 5 will be considered.
Select tables optimized away
The query contained only aggregate functions (
MIN(),
MAX())
that were all resolved using an index, or
COUNT(*)for
MyISAM,
and no
GROUP BYclause. The optimizer
determined that only one row should be returned.
unique row not found
For a query such as
SELECT ... FROM tbl_name,
no rows satisfy the condition for a
UNIQUEindex
or
PRIMARY KEYon the table.
Using filesort
MySQL must do an extra pass to find out how to retrieve the rows in sorted order. The sort is done by going through all rows according to the join type and storing the sort key and pointer to the row for all rows that match the
WHEREclause.
The keys then are sorted and the rows are retrieved in sorted order. See Section 8.3.1.11,
“
ORDER BYOptimization”.
Using index
The column information is retrieved from the table using only information in the index tree without having to do an additional seek to read the actual row. This strategy can be used when the query uses only columns that are part of a single index.
If the
Extracolumn also says
Using where, it means the index is being used to perform lookups of key values. Without
Using where, the optimizer may be reading the index to avoid reading data rows but not using it for lookups. For example, if the index is a covering index for the query, the optimizer may scan it without using it for lookups.
Using index for group-by
Similar to the
Using indextable access
method,
Using index for group-byindicates
that MySQL found an index that can be used to retrieve all columns of a
GROUP BYor
DISTINCTquery without any
extra disk access to the actual table. Additionally, the index is used in the most efficient way so that for each group, only a few index entries are read. For details, see Section 8.3.1.12,
“
GROUP BYOptimization”.
Using sort_union(...),
Using union(...),
Using intersect(...)
These indicate how index scans are merged for the
index_mergejoin
type. See Section 8.3.1.4,
“Index Merge Optimization”.
Using temporary
To resolve the query, MySQL needs to create a temporary table to hold the result. This typically happens if the query contains
GROUP BYand
ORDER BYclauses that list
columns differently.
Using where
A
WHEREclause is used to restrict which
rows to match against the next table or send to the client. Unless you specifically intend to fetch or examine all rows from the table, you may have something wrong in your query if the
Extravalue
is not
Using whereand the table join
type is
ALLor
index.
Even if you are using an index for all parts of a
WHEREclause,
you may see
Using whereif the column
can be
NULL.
Using where with pushed condition
This item applies to
NDBCLUSTERtables only.
It means that MySQL Cluster is using the Condition Pushdown optimization to improve the efficiency of a direct comparison between a nonindexed column and a constant. In such cases, the condition is “pushed
down” to the cluster's data nodes and is evaluated on all data nodes simultaneously. This eliminates the need to send nonmatching rows over the network, and can speed up such queries by a factor of 5 to 10 times over cases where Condition Pushdown
could be but is not used. For more information, see Section 8.3.1.5,
“Engine Condition Pushdown Optimization”.
EXPLAIN
Output
Interpretation
You can get a good indication of how good a join is by taking the product of the values in the rowscolumn
of the
EXPLAINoutput.
This should tell you roughly how many rows MySQL must examine to execute the query. If you restrict queries with the
max_join_sizesystem
variable, this row product also is used to determine which multiple-table
SELECTstatements
to execute and which to abort. See Section 8.9.2,
“Tuning Server Parameters”.
The following example shows how a multiple-table join can be optimized progressively based on the information provided by
EXPLAIN.
Suppose that you have the
SELECTstatement
shown here and that you plan to examine it using
EXPLAIN:
EXPLAIN SELECT tt.TicketNumber, tt.TimeIn, tt.ProjectReference, tt.EstimatedShipDate, tt.ActualShipDate, tt.ClientID, tt.ServiceCodes, tt.RepetitiveID, tt.CurrentProcess, tt.CurrentDPPerson, tt.RecordVolume, tt.DPPrinted, et.COUNTRY, et_1.COUNTRY, do.CUSTNAME FROM tt, et, et AS et_1, do WHERE tt.SubmitTime IS NULL AND tt.ActualPC = et.EMPLOYID AND tt.AssignedPC = et_1.EMPLOYID AND tt.ClientID = do.CUSTNMBR;
For this example, make the following assumptions:
The columns being compared have been declared as follows.
Table | Column | Data Type |
---|---|---|
tt | ActualPC | CHAR(10) |
tt | AssignedPC | CHAR(10) |
tt | ClientID | CHAR(10) |
et | EMPLOYID | CHAR(15) |
do | CUSTNMBR | CHAR(15) |
Table | Index |
---|---|
tt | ActualPC |
tt | AssignedPC |
tt | ClientID |
et | EMPLOYID(primary key) |
do | CUSTNMBR(primary key) |
tt.ActualPCvalues are not evenly distributed.
Initially, before any optimizations have been performed, the
EXPLAINstatement
produces the following information:
table type possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 do ALL PRIMARY NULL NULL NULL 2135 et_1 ALL PRIMARY NULL NULL NULL 74 tt ALL AssignedPC, NULL NULL NULL 3872 ClientID, ActualPC Range checked for each record (index map: 0x23)
Because
typeis
ALLfor
each table, this output indicates that MySQL is generating a Cartesian product of all the tables; that is, every combination of rows. This takes quite a long time, because the product of the number of rows in each table must be examined. For the case at hand,
this product is 74 × 2135 × 74 × 3872 = 45,268,558,720 rows. If the tables were bigger, you can only imagine how long it would take.
One problem here is that MySQL can use indexes on columns more efficiently if they are declared as the same type and size. In this context,
VARCHARand
CHARare
considered the same if they are declared as the same size.
tt.ActualPCis
declared as
CHAR(10)and
et.EMPLOYIDis
CHAR(15),
so there is a length mismatch.
To fix this disparity between column lengths, use
ALTER TABLEto lengthen
ActualPCfrom
10 characters to 15 characters:
mysql> [code]ALTER TABLE tt MODIFY ActualPC VARCHAR(15);
[/code]
Now
tt.ActualPCand
et.EMPLOYIDare
both
VARCHAR(15). Executing the
EXPLAINstatement
again produces this result:
table type possible_keys key key_len ref rows Extra tt ALL AssignedPC, NULL NULL NULL 3872 Using ClientID, where ActualPC do ALL PRIMARY NULL NULL NULL 2135 Range checked for each record (index map: 0x1) et_1 ALL PRIMARY NULL NULL NULL 74 Range checked for each record (index map: 0x1) et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
This is not perfect, but is much better: The product of the
rowsvalues
is less by a factor of 74. This version executes in a couple of seconds.
A second alteration can be made to eliminate the column length mismatches for the
tt.AssignedPC = et_1.EMPLOYIDand
tt.ClientID = do.CUSTNMBRcomparisons:
mysql> [code]ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),
->
MODIFY ClientID VARCHAR(15);
[/code]
After that modification,
EXPLAINproduces
the output shown here:
table type possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 tt ref AssignedPC, ActualPC 15 et.EMPLOYID 52 Using ClientID, where ActualPC et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1 do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
At this point, the query is optimized almost as well as possible. The remaining problem is that, by default, MySQL assumes that values in the
tt.ActualPCcolumn
are evenly distributed, and that is not the case for the
tttable.
Fortunately, it is easy to tell MySQL to analyze the key distribution:
mysql> [code]ANALYZE TABLE tt;
[/code]
With the additional index information, the join is perfect and
EXPLAINproduces
this result:
table type possible_keys key key_len ref rows Extra tt ALL AssignedPC NULL NULL NULL 3872 Using ClientID, where ActualPC et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1 et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1 do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
Note that the
rowscolumn
in the output from
EXPLAINis
an educated guess from the MySQL join optimizer. You should check whether the numbers are even close to the truth by comparing the
rowsproduct
with the actual number of rows that the query returns. If the numbers are quite different, you might get better performance by using
STRAIGHT_JOINin
your
SELECTstatement
and trying to list the tables in a different order in the
FROMclause.
It is possible in some cases to execute statements that modify data when
EXPLAIN SELECTis used with a subquery; for more information, see Section 13.2.9.8,
“Subqueries in the
FROMClause”.
相关文章推荐
- mysql中explain用法和结果的含义
- mysql中explain用法和结果的含义
- php实习tips(mysql_query的结果返回值与判断)
- MYSQL优化浅谈,工具及优化点介绍,mysqldumpslow,pt-query-digest,explain等
- MySQL Explain 结果解读与实践
- mysql explain中的type列含义和extra列的含义
- mysql explain type 和extra 列的含义
- mysql中explain执行结果中的rows是什么意思?
- MySQL里执行SHOW INDEX结果中Cardinality的含义
- MySQL通过Explain查看select语句的执行计划结果触发写操作
- MYSQL --Subquery returns more than 1 row查询结果多于一行
- MYSQL --Subquery returns more than 1 row查询结果多于一行
- mysql_query() select 的结果都是零
- 关于mysql 数据库使用spring 2.0低版本 JdbcTemplate.queryForList 查询结果别名不起作用的解决方法
- MySQL里执行SHOW INDEX结果中Cardinality的含义
- MYSQL --Subquery returns more than 1 row查询结果多于一行
- MySQL与Oracle主键Query性能测试结果
- mysql explain用法和结果的含义
- php mysql_query中insert结果偏差
- mysql EXPLAIN sql语句 各个字段代表的含义(转载)