MySQL EXPLAIN 实践汇总(操练)

MySQLEXPLAIN可以显示估计查询语句执行计划,从中可以分析查询的执行情况是不是最优,这有助于我们对不使用索引的查询进行优化。EXPLAIN对于每个查询语句返回一行信息,它列出了一个有序的表格,MySQL处理语句的时候会读取他们。MySQL解决所有的连接都使用嵌套连接方法。这意味着MySQL读取第一张一行,然后匹配第二张表的所有行,第三张表或更多表都如此。当所有的表在处理时,MySQL会输出已经查询出来的列,并且回溯到表继续查找直到所有的行被找到,从该表读取下一行,直到程序继续处理下一张表。

当使用关键词 EXTENDED 时,EXPLAIN 会处理通过 SHOW WARNINGS 看到的一些而外信息。EXPLAIN EXTENDED 也会显示这些滤出的列。
语法:

EXPLAIN <select statement>;

输出表格字段如下:

mysql> explain select * from mysql.user where user='root';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | user  | ALL  | NULL          | NULL | NULL    | NULL |    4 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+

以下主要举例说明3个字段:select_type 、type、Extra 

 


创建测试表:

create table tabname (
id int auto_increment not null primary key,
name varchar(10) null,
indate datetime null,
tid int null,
key(tid),
key(indate)
)engine=innodb;


create table tabname2 (
id int auto_increment not null primary key,
name varchar(10) null,
indate datetime null,
tid int null,
key(tid),
key(indate)
)engine=myisam;


insert into tabname(name,indate,tid) values('love',now(),2),('lucky',now(),3),('passion',now(),4);
insert into tabname2(name,indate,tid) values('love',now(),2),('lucky',now(),3),('passion',now(),4);


#SIMPLE

mysql> explain select * from tabname;
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | tabname | ALL  | NULL          | NULL | NULL    | NULL |    3 |       |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+

#PRIMARY / DERIVED

mysql> explain select * from (select * from tabname) as a;
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
|  1 | PRIMARY     | <derived2> | ALL  | NULL          | NULL | NULL    | NULL |    3 |       |
|  2 | DERIVED     | tabname    | ALL  | NULL          | NULL | NULL    | NULL |    3 |       |
+----+-------------+------------+------+---------------+------+---------+------+------+-------+

#PRIMARY / UNION / UNION RESULT

mysql> explain select * from tabname union select * from tabname;
mysql> explain select * from tabname union all select * from tabname;
+----+--------------+------------+------+---------------+------+---------+------+------+-------+
| id | select_type  | table      | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+--------------+------------+------+---------------+------+---------+------+------+-------+
|  1 | PRIMARY      | tabname    | ALL  | NULL          | NULL | NULL    | NULL |    3 |       |
|  2 | UNION        | tabname    | ALL  | NULL          | NULL | NULL    | NULL |    3 |       |
| NULL | UNION RESULT | <union1,2> | ALL  | NULL          | NULL | NULL    | NULL | NULL |       |
+----+--------------+------------+------+---------------+------+---------+------+------+-------+

#PRIMARY / SUBQUERY

mysql> explain select * from tabname where id=(select max(id) from tabname);
+----+-------------+---------+-------+---------------+---------+---------+-------+------+------------------------------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref   | rows | Extra                        |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+------------------------------+
|  1 | PRIMARY     | tabname | const | PRIMARY       | PRIMARY | 4       | const |    1 |                              |
|  2 | SUBQUERY    | NULL    | NULL  | NULL          | NULL    | NULL    | NULL  | NULL | Select tables optimized away |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+------------------------------+

#PRIMARY / DEPENDENT SUBQUERY

mysql> explain select * from tabname a where exists(select 1 from tabname b where a.id=b.id);
mysql> explain select *,(select name from tabname b where a.id=b.id) from tabname a;
mysql> explain select * from tabname where id not in(select id from tabname);
+----+--------------------+---------+-----------------+---------------+---------+---------+------+------+-------------+
| id | select_type        | table   | type            | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+--------------------+---------+-----------------+---------------+---------+---------+------+------+-------------+
|  1 | PRIMARY            | tabname | ALL             | NULL          | NULL    | NULL    | NULL |    3 | Using where |
|  2 | DEPENDENT SUBQUERY | tabname | unique_subquery | PRIMARY       | PRIMARY | 4       | func |    1 | Using index |
+----+--------------------+---------+-----------------+---------------+---------+---------+------+------+-------------+

#PRIMARY / DEPENDENT UNION / DEPENDENT SUBQUERY / UNION RESULT

mysql> explain select * from tabname where id in (select id from tabname union select id from tabname);
+----+--------------------+------------+--------+---------------+---------+---------+------+------+-------------+
| id | select_type        | table      | type   | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+--------------------+------------+--------+---------------+---------+---------+------+------+-------------+
|  1 | PRIMARY            | tabname    | ALL    | NULL          | NULL    | NULL    | NULL |    3 | Using where |
|  2 | DEPENDENT SUBQUERY | tabname    | eq_ref | PRIMARY       | PRIMARY | 4       | func |    1 | Using index |
|  3 | DEPENDENT UNION    | tabname    | eq_ref | PRIMARY       | PRIMARY | 4       | func |    1 | Using index |
| NULL| UNION RESULT      | <union2,3> | ALL    | NULL          | NULL    | NULL    | NULL | NULL |             |
+----+--------------------+------------+--------+---------------+---------+---------+------+------+-------------+

【type】


查询类型性能由优到差:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

#system

mysql> explain select id from(select id from tabname where id=1) as a;
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+
| id | select_type | table      | type   | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+
|  1 | PRIMARY     | <derived2> | system | NULL          | NULL    | NULL    | NULL |    1 |             |
|  2 | DERIVED     | tabname    | const  | PRIMARY       | PRIMARY | 4       |      |    1 | Using index |
+----+-------------+------------+--------+---------------+---------+---------+------+------+-------------+

#const
mysql> explain select * from tabname as a,tabname as b where a.id=b.id and a.id=1;
mysql> explain select * from tabname where id=1;
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | tabname | const | PRIMARY       | PRIMARY | 4       | const |    1 |       |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+

#eq_ref(engine=myisam)
mysql> explain select * from tabname2 as a,tabname2 as b where a.id=b.id;
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+-------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref       | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+-------+
|  1 | SIMPLE      | a     | ALL    | PRIMARY       | NULL    | NULL    | NULL      |    3 |       |
|  1 | SIMPLE      | b     | eq_ref | PRIMARY       | PRIMARY | 4       | test.a.id |    1 |       |
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+-------+
#ref

mysql> explain select * from tabname as a,tabname as b where a.tid=b.tid and a.tid=2;
mysql> explain select * from tabname where tid=2;
+----+-------------+---------+------+---------------+------+---------+-------+------+-------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref   | rows | Extra       |
+----+-------------+---------+------+---------------+------+---------+-------+------+-------------+
|  1 | SIMPLE      | tabname | ref  | tid           | tid  | 5       | const |    1 | Using where |
+----+-------------+---------+------+---------------+------+---------+-------+------+-------------+
#ref_or_null

mysql> explain select id,tid from tabname where tid=2 or tid is null;
+----+-------------+---------+-------------+---------------+------+---------+-------+------+--------------------------+
| id | select_type | table   | type        | possible_keys | key  | key_len | ref   | rows | Extra                    |
+----+-------------+---------+-------------+---------------+------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | tabname | ref_or_null | tid           | tid  | 5       | const |    2 | Using where; Using index |
+----+-------------+---------+-------------+---------------+------+---------+-------+------+--------------------------+
#fulltext

mysql> alter table tabname2 add fulltext(name);
mysql> explain select * from tabname2 where match(name) against('love');
+----+-------------+----------+----------+---------------+------+---------+------+------+-------------+
| id | select_type | table    | type     | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+----------+----------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | tabname2 | fulltext | name          | name | 0       |      |    1 | Using where |
+----+-------------+----------+----------+---------------+------+---------+------+------+-------------+
#index_merge(未成功)

mysql> explain select * from tabname where tid>1 or indate<now();
mysql> explain select * from tabname where (tid>1 or indate>now()) AND name<'kk';

#unique_subquery
mysql> explain select * from tabname where tid in(select id from tabname);
mysql> explain select * from tabname where id in(select id from tabname);
+----+--------------------+---------+-----------------+---------------+---------+---------+------+------+-------------+
| id | select_type        | table   | type            | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+--------------------+---------+-----------------+---------------+---------+---------+------+------+-------------+
|  1 | PRIMARY            | tabname | ALL             | NULL          | NULL    | NULL    | NULL |    3 | Using where |
|  2 | DEPENDENT SUBQUERY | tabname | unique_subquery | PRIMARY       | PRIMARY | 4       | func |    1 | Using index |
+----+--------------------+---------+-----------------+---------------+---------+---------+------+------+-------------+
#index_subquery

mysql> explain select * from tabname where tid in(select tid from tabname);
mysql> explain select * from tabname where id in(select tid from tabname);
+----+--------------------+---------+----------------+---------------+------+---------+------+------+--------------------------+
| id | select_type        | table   | type           | possible_keys | key  | key_len | ref  | rows | Extra                    |
+----+--------------------+---------+----------------+---------------+------+---------+------+------+--------------------------+
|  1 | PRIMARY            | tabname | ALL            | NULL          | NULL | NULL    | NULL |    3 | Using where              |
|  2 | DEPENDENT SUBQUERY | tabname | index_subquery | tid           | tid  | 5       | func |    1 | Using index; Using where |
+----+--------------------+---------+----------------+---------------+------+---------+------+------+--------------------------+
#range

mysql> explain select * from tabname where tid between 1 and 2;
mysql> explain select * from tabname where id>1;
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | tabname | range | PRIMARY       | PRIMARY | 4       | NULL |    2 | Using where |
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
#index

mysql> explain select id,tid from tabname;
mysql> explain select tid from tabname;
+----+-------------+---------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table   | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | tabname | index | NULL          | tid  | 5       | NULL |    3 | Using index |
+----+-------------+---------+-------+---------------+------+---------+------+------+-------------+
#ALL

mysql> explain select * from tabname where tid<>2;
mysql> explain select * from tabname;
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | tabname | ALL  | NULL          | NULL | NULL    | NULL |    3 |       |
+----+-------------+---------+------+---------------+------+---------+------+------+-------+

【Extra】

该列输出关MySQL如何解决查询的额外信息。(下面列出部分常见的)


#using where

mysql> explain select * from tabname where id>2;
mysql> explain select * from tabname where tid=2;
+----+-------------+---------+------+---------------+------+---------+-------+------+-------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref   | rows | Extra       |
+----+-------------+---------+------+---------------+------+---------+-------+------+-------------+
|  1 | SIMPLE      | tabname | ref  | tid           | tid  | 5       | const |    1 | Using where |
+----+-------------+---------+------+---------------+------+---------+-------+------+-------------+

#using index
mysql> explain select tid from tabname;
+----+-------------+---------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table   | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | tabname | index | NULL          | tid  | 5       | NULL |    3 | Using index |
+----+-------------+---------+-------+---------------+------+---------+------+------+-------------+
#using temporary

mysql> explain select distinct name from tabname;
+----+-------------+---------+------+---------------+------+---------+------+------+-----------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra           |
+----+-------------+---------+------+---------------+------+---------+------+------+-----------------+
|  1 | SIMPLE      | tabname | ALL  | NULL          | NULL | NULL    | NULL |    3 | Using temporary |
+----+-------------+---------+------+---------------+------+---------+------+------+-----------------+

#select tables optimized away
mysql> explain select max(tid) from tabname;
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra                        |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Select tables optimized away |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
#using filesort

mysql> explain select id,name from tabname group by id,name;
mysql> explain select * from tabname order by name;
+----+-------------+---------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+---------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | tabname | ALL  | NULL          | NULL | NULL    | NULL |    3 | Using filesort |
+----+-------------+---------+------+---------------+------+---------+------+------+----------------+
#not exists

mysql> explain select * from tabname a left join tabname b on a.id=b.id where b.id is null;
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+-------------------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref       | rows | Extra                   |
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+-------------------------+
|  1 | SIMPLE      | a     | ALL    | NULL          | NULL    | NULL    | NULL      |    3 |                         |
|  1 | SIMPLE      | b     | eq_ref | PRIMARY       | PRIMARY | 4       | test.a.id |    1 | Using where; Not exists |
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+-------------------------+
#distinct

mysql> explain select distinct a.id from tabname a left join tabname b on a.id=b.id;
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+------------------------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref       | rows | Extra                        |
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+------------------------------+
|  1 | SIMPLE      | a     | index  | NULL          | tid     | 5       | NULL      |    3 | Using index; Using temporary |
|  1 | SIMPLE      | b     | eq_ref | PRIMARY       | PRIMARY | 4       | test.a.id |    1 | Using index; Distinct        |
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+------------------------------+
#impossible where

mysql> explain select * from tabname where 1=2;
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra            |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible WHERE |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------+

#impossible having
mysql> explain select id,count(*) from tabname group by id having 1=2;
mysql> explain select count(*) from tabname having 1=2;
+----+-------------+-------+------+---------------+------+---------+------+------+-------------------+
| id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra             |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------------+
|  1 | SIMPLE      | NULL  | NULL | NULL          | NULL | NULL    | NULL | NULL | Impossible HAVING |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------------+


#usingjoin buffer

#Using index for group-by


=====================================================================================

=====================================================================================

现在使用 EXTENDED 情况:

语法:

EXPLAIN EXTENDED <select statement>;

不使用 extended 和使用extended 的分析情况:
mysql> explain select tid from tabname;
+----+-------------+---------+-------+---------------+------+---------+------+------+-------------+
| id | select_type | table   | type  | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+---------+-------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | tabname | index | NULL          | tid  | 5       | NULL |    3 | Using index |
+----+-------------+---------+-------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> explain extended select tid from tabname;
+----+-------------+---------+-------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table   | type  | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+---------+-------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | tabname | index | NULL          | tid  | 5       | NULL |    3 |   100.00 | Using index |
+----+-------------+---------+-------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

可以看到,使用 extended 时,输出的最下面多了 1 条警告。 此时可以用 show warnings 来查看:
mysql> show warnings \G;
*************************** 1. row ***************************
  Level: Note
   Code: 1003
Message: select `test`.`tabname`.`tid` AS `tid` from `test`.`tabname`
1 row in set (0.00 sec)

ERROR:
No query specified

show warnings 显示了优化器中是怎么规范表和字段名的,在通过重写和优化规则之后的 select 语句是什么样子。


更多参考:

EXPLAIN Output Format

https://dev.mysql.com/doc/refman/5.7/en/explain-output.html

EXPLAIN EXTENDED Output Format

https://dev.mysql.com/doc/refman/5.7/en/explain-extended.html


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值