您的位置:首页 > 数据库 > MySQL

每日MySQL之020:使用EXPLAIN查看SQL的执行计划

2017-08-13 20:37 816 查看
MySQL中要查看执行计划,可以使用EXPLAIN命令,EXPLAIN 使用的对象是 SELECT, DELETE, INSERT, REPLACE, 和 UPDATE 语句。将EXPLAIN换成DESCRIBE也行,两者含义一样,但实际操作中一般用DESCRIBE查看表结构,用EXPLAIN查看执行计划。输出的结果不是图形化的,而是一张表。对于每个SELECT语句中的每个表,EXPLAIN都会返回一行。返回的顺序就是MySQL读取表的顺序。MySQL使用nested-loop join来完成所有的join工作。

先来看两个简单的例子,第一个SELECT语句访问一张表,只有一行输出。第二个SELECT语句访问两张表,就有两行输出,table列指定了访问的表名:

mysql> EXPLAIN SELECT id, age from t1;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | t1    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    6 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

mysql> EXPLAIN SELECT t1.id, t1.age, t2.name FROM t1,t2;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                                 |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+
|  1 | SIMPLE      | t2    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    4 |   100.00 | NULL                                  |
|  1 | SIMPLE      | t1    | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    6 |   100.00 | Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+---------------------------------------+
2 rows in set, 1 warning (0.01 sec)


再详细看一下各个字段的含义,假设我们有以下三张表:

mysql> CREATE TABLE `t1` (id int, age int, KEY `idx1` (`id`));
mysql> CREATE TABLE `t2` ( `id` int(11),`name` char(15));
mysql> CREATE TABLE `t3` (id int not null primary key, name char(30));

mysql> INSERT INTO `t1` VALUES (1001,24),(1002,25),(1003,43),(1004,44),(1006,31),(1005,23);
mysql> INSERT INTO `t2` VALUES (1002,'name1'),(1005,'name2'),(1007,'name3'),(1010,'name4');
mysql> INSERT INTO `t3` VALUES (10086, 'Mobile'),(10011, 'Unicom'),(95583,'CommercialBank'),(12355,'taxiBue'),(1010,'aa');

mysql> ANALYZE TABLE t1;
mysql> ANALYZE TABLE t2;
mysql> ANALYZE TABLE t3;

mysql> select * from t1;
+------+------+
| id   | age  |
+------+------+
| 1001 |   24 |
| 1002 |   25 |
| 1003 |   43 |
| 1004 |   44 |
| 1006 |   31 |
| 1005 |   23 |
+------+------+
6 rows in set (0.01 sec)

mysql> select * from t2;
+------+-------+
| id   | name  |
+------+-------+
| 1002 | name1 |
| 1005 | name2 |
| 1007 | name3 |
| 1010 | name4 |
+------+-------+
4 rows in set (0.00 sec)

mysql> select * from t3;
+-------+----------------+
| id    | name           |
+-------+----------------+
|  1010 | aa             |
| 10011 | Unicom         |
| 10086 | Mobile         |
| 12355 | taxiBue        |
| 95583 | CommercialBank |
+-------+----------------+
5 rows in set (0.00 sec)

id (JSON name: select_id)

SELECT ID, 查询语句中SELECT的编号。如果是union的结果,可能为空值,这时table column显示的是<unionM,N>。 

示例1: 第一个语句有两个SELECT语句,所以有两个id,第二个语句有三个SELECT,所以有三个id,UNION RESULT的id为空:

mysql> EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t2;
+----+--------------+------------+
| id | select_type  | table      |
+----+--------------+------------+
|  1 | PRIMARY      | t1         |
|  2 | UNION        | t2         |
|NULL| UNION RESULT | <union1,2> |
+----+--------------+------------+
3 rows in set, 1 warning (0.00 sec)

mysql> EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t2 UNION SELECT * FROM t3;
+----+--------------+--------------+
| id | select_type  | table        |
+----+--------------+--------------+
|  1 | PRIMARY      | t1           |
|  2 | UNION        | t2           |
|  3 | UNION        | t3           |
|NULL| UNION RESULT | <union1,2,3> |
+----+--------------+--------------+
4 rows in set, 1 warning (0.00 sec)


select_type (JSON name: none)

SIMPLE:简单查询(不使用UNION或者子查询)

PRIMARY: 最外边SELECT

UNION: UNION中第二个及以后的SELECT

参考示例1。

table (JSON name: table_name)

表名。

partitions (JSON name: partitions)

分区表的分区名,对于非分区表,为NULL

type (JSON name: access_type)

Join type,可以参考:链接http://blog.csdn.net/qingsong3333/article/details/77149845

possible_keys (JSON name: possible_keys)

可能选择的索引

key (JSON name: key)

最终选择的索引

示例2,第一条SELECT没有使用索引, 第二条使用了索引idx1,第三条使用了PRIMARY KEY。

mysql> EXPLAIN SELECT * FROM t1 where id < 1005;
+----+-------------+-------+...+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table |...| possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+...+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | t1    |...| idx1          | NULL | NULL    | NULL |    6 |    66.67 | Using where |
+----+-------------+-------+...+---------------+------+---------+------+------+----------+-------------+

mysql> EXPLAIN SELECT * FROM t1 where id > 1004;
+----+-------------+-------+...+---------------+------+---------+------+------+----------+-----------------------+
| id | select_type | table |...| possible_keys | key  | key_len | ref  | rows | filtered | Extra                 |
+----+-------------+-------+...+---------------+------+---------+------+------+----------+-----------------------+
|  1 | SIMPLE      | t1    |...| idx1          | idx1 | 5       | NULL |    2 |   100.00 | Using index condition |
+----+-------------+-------+...+---------------+------+---------+------+------+----------+-----------------------+

mysql> EXPLAIN SELECT * FROM t3 where id > 10010;
+----+-------------+-------+...+---------------+---------+---------+------+------+----------+-------------+
| id | select_type | table |...| possible_keys | key     | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+...+---------------+---------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | t3    |...| PRIMARY       | PRIMARY | 4       | NULL |    4 |   100.00 | Using where |
+----+-------------+-------+...+---------------+---------+---------+------+------+----------+-------------+

key_len (JSON name: key_length)

key的长度

rows (JSON name: rows)

MySQL认为完成查询需要访问的行数,只是个估计值。

filtered (JSON name: filtered)

被条件过滤掉的百分比。That is, rows shows the estimated number of rows examined and rows × filtered / 100

shows the number of rows that will be joined with previous tables.

Extra (JSON name: none)

额外说明

另外,可以设置 FORMAT 参数,如果设为JSON,则显示为JSON格式:
mysql> EXPLAIN FORMAT=JSON SELECT id, age from t1 \G
*************************** 1. row ***************************
EXPLAIN: {
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "2.20"
},
"table": {
"table_name": "t1",
"access_type": "ALL",
"rows_examined_per_scan": 6,
"rows_produced_per_join": 6,
"filtered": "100.00",
"cost_info": {
"read_cost": "1.00",
"eval_cost": "1.20",
"prefix_cost": "2.20",
"data_read_per_join": "96"
},
"used_columns": [
"id",
"age"
]
}
}
}
1 row in set, 1 warning (0.00 sec)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MySQL EXPLAIN 执行计划