- EXPLAIN 会为 SELECT 语句中使用的每个表返回一行信息。它按照 MySQL 在处理语句时读取它们的顺序列出输出中的表。这意味着 MySQL 从第一个表中读取一行,然后在第二个表中找到匹配的行,然后在第三个表中,依此类推。当所有的表都被处理完后,MySQL 将选择的列输出,并在表列表中回溯,直到找到一个有更多匹配行的表。从此表中读取下一行,然后继续处理下一个表
- 在 EXPLAIN 的帮助下,我们可以看到应该在表的何处添加索引,通过扫描索引获取查找特定行来更快地执行语句。还可以使用 EXPLAIN 检查优化器是否以最佳顺序连接表,优化复杂的连接查询。
语法
{EXPLAIN | DESCRIBE | DESC}
[FORMAT = TRADITIONAL | JSON | TREE]
{explainable_stmt | FOR CONNECTION connection_id};
参数 |
描述 |
explainable_stmt: { |
可解释语句,即增删改查 SQL 语句 |
connection_id |
命名连接中执行的语句的执行计划。 |
示例
EXPLAIN SELECT * FROM users WHERE uname Like '张%';
运行结果如下(TRADITIONAL):
+----+---------------+----------+-------------+-------+-----------------+------------+----------+--------+-------+----------+---------------+
| id |
select_type | table |
partitions | type | possible_keys |
key |
key_len | ref | rows | filtered |
Extra |
+----+---------------+----------+-------------+-------+-----------------+------------+----------+--------+-------+----------+---------------+
| 1 | SIMPLE | country | NULL |
range | PRIMARY | PRIMARY | 12 | NULL |
17 | 100.00 | Using where
|
+----+---------------+----------+-------------+-------+-----------------+------------+----------+--------+-------+----------+---------------+
1 row in set, 1 warning (0.00 sec)
- 通过查询分析器的结果,可得知上面的查询语句是一个普通查询,进行了范围查询(range),没有使用任何索引,而是进行了全表扫描
- 通过检查查询分析器给出的主要参数,可以很好的优化查询语句的速度:
影响查询的参数 |
说明 |
select_type |
查询类型 |
partitions |
匹配的分区。查询将从中匹配记录的分区。对于未分区的表,该值为NULL |
type |
连接类型,描述了表是如何连接的。 |
possible_keys |
可供选择的索引。指示 MySQL 可以从中选择的索引来查找该表中的行。 |
key |
实际选择的索引。 |
key_len |
所选键的长度。key_len 的值使您能够确定 MySQL 实际使用多部分键的多少部分。如果键列为 NULL,则 key_len 列也为 NULL。 |
ref |
与索引比较的列。ref列显示将哪些列或常量与键列中命名的索引进行比较,以便从表中选择行。 |
rows |
rows列表示MySQL认为执行查询必须检查的行数。 |
filtered |
已筛选列表示按表条件筛选的表行的估计百分比。最大值为100(最佳),这意味着没有对行进行筛选 |
extra |
包含有关 MySQL 如何解析查询的附加信息。 |
- 对于查询分析的连接类型(type),查询速度的优先级为:
system
> const
> eq_ref
> ref
> ref_or_null
> index_merge
> unique_subquery
> index_subquery
> range
> index
> ALL
注
- 要提示优化器使用与表在 SELECT 语句中的命名顺序相对应的连接顺序,请以 SELECT STRAIGHT_JOIN 而不是只是 SELECT 开始该语句。但是,STRAIGHT_JOIN 可能会阻止使用索引,因为它禁用了半连接转换
- 对于InnoDB表,row 参数的值只是一个估计值,可能并不总是准确的。