介绍

  本篇主要通过汇总网上的大牛的知识,简单介绍一下如何使用mysql的执行计划,并根据执行计划判断如何优化和是否索引最优。

  执行计划可显示估计查询语句执行计划,从中可以分析查询的执行情况是否最优,有助于对不使用索引的语句进行优化。EXPLAIN对每个查询返回一行信息,列出了有序的表格,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 |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| | SIMPLE | user | ALL | NULL | NULL | NULL | NULL | | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+

Column

JSONName

Meaning

id

select_id

查询标识。id越大优先执行;id相同自上而下执行;

select_type

None

查询的类型

table

table_name

查询的表

partitions

partitions

Thematching partitions

type

access_type

连接类型

possible_keys

possible_keys

可能选择的索引

key

key

实际使用的索引

key_len

key_length

使用的索引长度

ref

ref

哪一列或常数在查询中与索引键列一起使用

rows

rows

估计查询的行数

filtered

filtered

被条件过滤掉的行数百分比

Extra

None

解决查询的一些额外信息

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

select_type

alue

JSONName

Meaning

SIMPLE

None

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

PRIMARY

None

外层查询,主查询

UNION

None

UNION第二个语句或后面的语句

DEPENDENTUNION

dependent (true)

UNION中第二个语句或后面的语句,独立于外部查询

UNIONRESULT

union_result

UNION的结果

SUBQUERY

None

子查询中第一个SELECT

DEPENDENTSUBQUERY

dependent (true)

子查询中第一个SELECT,独立于外部查询

DERIVED

None

子查询在 FROM子句中

MATERIALIZED

materialized_from_subquery

物化子查询(不清楚是什么样的查询语句?)

UNCACHEABLESUBQUERY

cacheable (false)

结果集不能被缓存的子查询,必须重新评估外层查询的每一行

UNCACHEABLEUNION

cacheable (false)

UNION中第二个语句或后面的语句属于不可缓存的子查询

创建测试表:

create table tabname (
id int auto_increment not null primary key,
name varchar() 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() null,
indate datetime null,
tid int null,
key(tid),
key(indate)
)engine=myisam; insert into tabname(name,indate,tid) values('love',now(),),('lucky',now(),),('passion',now(),);
insert into tabname2(name,indate,tid) values('love',now(),),('lucky',now(),),('passion',now(),);

#SIMPLE

#PRIMARY / DERIVED

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

#PRIMARY / UNION / UNION RESULT

    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 |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+------------------------------+
| | PRIMARY | tabname | const | PRIMARY | PRIMARY | | const | | |
| | SUBQUERY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Select tables optimized away |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+------------------------------+

#PRIMARY / SUBQUERY

 

#PRIMARY / DEPENDENT SUBQUERY

    mysql> explain select * from tabname a where exists(select  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 |
+----+--------------------+---------+-----------------+---------------+---------+---------+------+------+-------------+
| | PRIMARY | tabname | ALL | NULL | NULL | NULL | NULL | | Using where |
| | DEPENDENT SUBQUERY | tabname | unique_subquery | PRIMARY | PRIMARY | | func | | 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 |
+----+--------------------+------------+--------+---------------+---------+---------+------+------+-------------+
| | PRIMARY | tabname | ALL | NULL | NULL | NULL | NULL | | Using where |
| | DEPENDENT SUBQUERY | tabname | eq_ref | PRIMARY | PRIMARY | | func | | Using index |
| | DEPENDENT UNION | tabname | eq_ref | PRIMARY | PRIMARY | | func | | Using index |
| NULL| UNION RESULT | <union2,> | ALL | NULL | NULL | NULL | NULL | NULL | |
+----+--------------------+------------+--------+---------------+---------+---------+------+------+-------------+

 

type

type

Meaning

system

表仅一行数据 (=system table).这是const连接类型的特例。

const

表最多只有一个匹配行,在查询开始时被读取。因为只有一个值,优化器将该列值视为常量。当在primarykey或者unique索引作为常量比较时被使用。

eq_ref(engine=myisam)

来自前面表的结果集中读取一行,这是除systemconst外最好的连接类型。当在使用PRIMARYKEY或者UNIQUENOT NULL的索引时会被使用。

ref

对于前面表的结果集匹配查询的所有行,当连接使用索引key时,或者索引不是PRIMARYKEYUNIQUE则使用该类型。如果使用索引匹配少量行时,是不错的连接类型。

ref_or_null

连接类型类似ref,只是搜索的行中包含NULLMySQL做了额外的查找。

fulltext

使用全文索引时出现。

index_merge

使用了索引合并优化。(未成功)

unique_subquery

该类型将ref替换成以下子查询的格式:

valueIN (SELECTprimary_key FROMsingle_table WHERE some_expr)

index_subquery

unique_subquery类似,但是将主键改为非唯一索引:

valueIN (SELECTkey_columnFROMsingle_table WHERE some_expr)

range

使用索引检索给定范围内的行。

index

该连接类型与ALL相同,除了扫描索引树。如果查询的字段都在索引列中,则使用index类型,否则为ALL类型。

ALL

对于前面表的结果集中,进行了全表扫描。最差的一种类型,应考虑查询优化了!

查询类型性能由优到差:

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

#system

#const

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

#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 |
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+-------+
| | SIMPLE | a | ALL | PRIMARY | NULL | NULL | NULL | | |
| | SIMPLE | b | eq_ref | PRIMARY | PRIMARY | | test.a.id | | |
+----+-------------+-------+--------+---------------+---------+---------+-----------+------+-------+
 

#ref

#ref_or_null

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

#fulltext

#index_merge(未成功)

#unique_subquery

#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 |
+----+--------------------+---------+----------------+---------------+------+---------+------+------+--------------------------+
| | PRIMARY | tabname | ALL | NULL | NULL | NULL | NULL | | Using where |
| | DEPENDENT SUBQUERY | tabname | index_subquery | tid | tid | | func | | Using index; Using where |
+----+--------------------+---------+----------------+---------------+------+---------+------+------+--------------------------+
 

#range

    mysql> explain select * from tabname where tid between  and ;
mysql> explain select * from tabname where id>;
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+------+------+-------------+
| | SIMPLE | tabname | range | PRIMARY | PRIMARY | | NULL | | 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 |
+----+-------------+---------+-------+---------------+------+---------+------+------+-------------+
| | SIMPLE | tabname | index | NULL | tid | | NULL | | Using index |
+----+-------------+---------+-------+---------------+------+---------+------+------+-------------+

#ALL

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

Extra

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

Extra

Meaning

usingwhere

使用过滤条件

usingindex

从索引树中查找所有列

usingtemporary

使用临时表存储结果集,在使用groupbyorderby发生

selecttables optimized away

没有groupby情况下使用min(),max(),或者count(*)

usingfilesort

有排序

notexists

在leftjoin中匹配一行之后将不再继续查询查询

distinct

查找到第一个匹配的行之后,MySQL则会停止对当前行的搜索

impossiblewhere

where子句总数失败的查询

impossiblehaving

having子句总数失败的查询

usingjoin buffer

使用连接缓存

Usingindex for group-by

Usingindex类似,在使用group-by时可从索引中找到字段

#using where

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

#using index

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

#using temporary

 
    mysql> explain select distinct name from tabname;
+----+-------------+---------+------+---------------+------+---------+------+------+-----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+------+-----------------+
| | SIMPLE | tabname | ALL | NULL | NULL | NULL | NULL | | 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 |
+----+-------------+-------+------+---------------+------+---------+------+------+------------------------------+
| | 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 |
+----+-------------+---------+------+---------------+------+---------+------+------+----------------+
| | SIMPLE | tabname | ALL | NULL | NULL | NULL | NULL | | Using filesort |
+----+-------------+---------+------+---------------+------+---------+------+------+----------------+
 

#not exists

#distinct

#impossible where

#impossible having

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

现在使用 EXTENDED 情况:

语法:

  1. EXPLAIN EXTENDED <select statement>;

不使用 extended 和使用extended 的分析情况:

可以看到,使用 extended 时,输出的最下面多了 1 条警告。 此时可以用 show warnings
来查看:

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

更多参考:

EXPLAIN Output Format

EXPLAIN EXTENDED Output Format

mysql执行计划简介的更多相关文章

  1. MySQL执行计划解读

    Explain语法 EXPLAIN SELECT …… 变体: 1. EXPLAIN EXTENDED SELECT …… 将执行计划“反编译”成SELECT语句,运行SHOW WARNINGS 可得 ...

  2. mysql执行计划

         烂sql不仅直接影响sql的响应时间,更影响db的性能,导致其它正常的sql响应时间变长.如何写好sql,学会看执行计划至关重要.下面我简单讲讲mysql的执行计划,只列出了一些常见的情况, ...

  3. 如何查看MySQL执行计划

    在介绍怎么查看MySQL执行计划前,我们先来看个后面会提到的名词解释: 覆盖索引: MySQL可以利用索引返回select列表中的字段,而不必根据索引再次读取数据文件 包含所有满足查询需要的数据的索引 ...

  4. mysql 执行计划的理解

    1.执行计划就是在sql语句之前加上explain,使用desc 也可以.2.desc有两个选项extended和partitions,desc extended 将原sql语句进行优化,通过show ...

  5. MySQL执行计划 EXPLAIN参数

    MySQL执行计划参数详解 转http://www.jianshu.com/p/7134286b3a09 MySQL数据库中,在SELECT查询语句前边加上“EXPLAIN”或者“DESC”关键字,即 ...

  6. 查看Mysql执行计划

    使用navicat查看mysql执行计划: 打开profile分析工具: 查看是否生效:show variable like ‘%profil%’; 查看进程:show processlist; 选择 ...

  7. MySQL 执行计划explain详解

    MySQL 执行计划explain详解 2015-08-10 13:56:27 分类: MySQL explain命令是查看查询优化器如何决定执行查询的主要方法.这个功能有局限性,并不总会说出真相,但 ...

  8. MYSQL 执行计划

    Explain语法 EXPLAIN SELECT …… 变体: 1. EXPLAIN EXTENDED SELECT …… 将执行计划“反编译”成SELECT语句,运行SHOW WARNINGS 可得 ...

  9. MySQL执行计划extra中的using index 和 using where using index 的区别

    本文出处:http://www.cnblogs.com/wy123/p/7366486.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...

随机推荐

  1. Linux下的压力测试工具:ab、http_load、webbench、siege

    一.ab 1.1 介绍 ab是apache自带的一款功能强大的测试工具.      安装了apache一般就自带了. 1.2 下载 同apache. 1.3 安装 同apache. 1.4 安装结果 ...

  2. Halcon一日一练:图像拼接技术

    图像拼接技术就是针对同一场景的一系列图片,根据图片的特征,比如位置,重叠部分等,拼接成一张大幅的宽视角的图像. 图像拼接要求拼接后图像最大程度的与原图一致,失真尽可能的小,并且要尽量做到天衣无缝即没有 ...

  3. mysql有多条记录的单个字段想存为一个字段显示的方法

    SELECT po.id,(SELECT GROUP_CONCAT(mr.member_type) as memberTypeList FROM prod_offer_member_rel mr WH ...

  4. rem是如何自适应的

    原文链接:http://caibaojian.com/web-app-rem.html 摘要:rem是相对于根元素<html>,这样就意味着,我们只需要在根元素确定一个px字号,则可以来算 ...

  5. 天猫精灵X1智能音箱使用感想

    11.22音箱到手,等了刚好一个月. 主要是测评语音交互功能. 测试条件:正宗普通话. 1)问天气.温度:表现良好.2)找手机功能:试了多次,每次都说手机号码格式不对3)小孩听故事:正常.但是开头会有 ...

  6. B树、B-树、B+树、B*树【转】,mysql索引

    B树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: B ...

  7. JavaScript函数的柯里化(currying)

    转载请注明出处:http://www.cnblogs.com/shamoyuu/p/currying.html 什么是js函数的currying /柯里化? 说到js的柯里化,相信很多朋友都会头大.或 ...

  8. 用SDL库播放yuy2 Packed mode

    #define SDL_YUY2_OVERLAY 0x32595559 /* Packed mode: Y0+U0+Y1+V0 */ if (SDL_Init(SDL_INIT_VIDEO) < ...

  9. IE浏览器因缓存问题未能成功向后端发送请求的几个解决办法

    这段时间前后端联调,解决IE.谷歌等浏览器兼容问题,真是让人有点焦头烂额,各种奇葩问题层出不穷,旧问题刚去,新麻烦又来,其中尤其以IE浏览器缓存的问题最多.有若干次都是因为这个缓存,使得前端的请求没有 ...

  10. APACHE服务器出现No input file specified.的完美解决方案

    启用REWRITE的伪静态功能的时候,首页可以访问,而访问内页的时候,就提示:“No input file specified.” 原因在于使用的PHP是fast_cgi模式,而在某些情况下,不能正确 ...