MySQL中SQL语句的执行计划,你理解了吗?
Posted 程序猿分享编程
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL中SQL语句的执行计划,你理解了吗?相关的知识,希望对你有一定的参考价值。
首先我们来看一下什么是执行计划:
执行计划就是解释select语句如何在数据库执行的、相关表是怎么连接、连接的次序、有哪些索引和索引使用、每个表的扫描数据量等等。简单来说,就是通过数据来分析select语句的执行情况;
怎么查看执行计划:查看执行需要用到关键字EXPLAIN,将EXPLAIN放在SQL语句的前面( EXPLAIN [EXTENDED] SELECT select_options ),如下图:
从上图可以看出,通过执行计划展示了表格数据,这个表格有id、select_type、table、partitions、type、possible_keys、key、key_len、ref、rows、filtered、extra等字段的信息,这些字段分别表示什么意思呢?下面具体介绍下:
1、id
执行计划的id 是select查询的序列号,标识执行顺序。注意有两种情况,具体如下:
1)、当id相同时,执行顺序从上到下执行。
左外连接,先执行左边后执行右边(例如:select * from user u left join custom_order co on u.id=co.creater 会先执行user表后执行custom_order),在执行计划中,user表应该在上面,custom_order在下面,如下图:
右外连接,先执行右边后执行左边(例如:select * from user u right join custom_order co on u.id=co.creater 会先执行custom_order表后执行user表),在执行计划中,custom_order表应该在上面,user在下面:
从上面的执行结果来看,和预计的一样。
2)、当id不相同时,id越大越先执行。
例如:select * from user where id=(select creater from custom_order where id=1),这个语句中的子查询会比主查询会先执行。那在explain select * from user where id=(select creater from custom_order where id=1) 中 custom_order 的id应该是2,user的id应该是1,实际是不是这样呢,如下图:
从结果中可以知道,执行结果和预计的一样;
2、select_type
执行计划的select_type是select语句的类型,用于区分各种查询;具体类型有以下几种:
1)、SIMPLE
简单的select语句,不使用union或子查询。如下图:
2)、PRIMARY
最外层的select语句。如下图:
3)、UNION
union中的第二个或后面的select语句。如下图:
4)、DEPENDENT UNION
union中的第二个或后面的select语句,取决于外面的查询。如下图:
5)、UNION RESULT
union的结果。如下图:
6)、SUBQUERY
子查询的第一个select语句。如下图:
7)、DEPENDENT SUBQUERY
子查询中的第一个select语句,取决于外面的查询。如下图:
8)、DERIVED
衍生表的select语句(在from列表中包含的子查询)。如下图:
3、table
语句查询中所涉及到的表。如下图:
4、partitions
查询涉及到的分区。如下图:
5、type
SQL语句的连接类型。具体个连接类型如下:(按照从效率高的类型到效率低的类型进行排序)
1)、system
表仅有一行(等于系统表)。这是const连接类型的一种特例。
2)、const
表最多有一个匹配行,它将在查询开始时被读取,常用于主键或唯一索引的定值查询。因为匹配行只有一行,所以查询速度很快。如下图(id是主键):
3)、eq_ref
唯一性索引扫描,对于前表的每一行,表中只有一行与之相匹配或者没有能匹配。常见于主键或唯一索引扫描。是除const类型和system类型外最快的类型。如下图:
4)、ref
非唯一性索引扫描,对于前表的每一行,表中可存在多个与之相匹配的行。如下图:
5)、ref_or_null
和ref类型一样,但是添加了mysql可以专门搜索包含NULL值的行。如下图:
6)、index_merge
标识使用了索引合并优化方法。如下图:
7)、unique_subquery
一个索引查找函数,可以完全替换子查询,效率更高。
8)、index_sugquery
类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引。
9)、range
只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引。key_len包含所使用索引的最长关键元素。在该类型中ref列为NULL。当使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比较关键字列时。如下图:
10)、index
扫描索引树。如果索引是复合索引,并且复合索引列满足select所需的所有数据,则仅扫描索引树,不需要回表。如下图:
11)、ALL
扫描全表。这是最差的情况,没有索引,进行完整的表扫描。如下图:
6、possible_keys
语句中能使用索引有哪些。如下图:
7、key
该语句执行的时候是使用的哪条索引。如下图:
8、key_len该语句执行时使用的索引长度(字节数)。如下图:
9、ref
该表的索引字段关联了哪张表的哪个字段。如下图:
10、rows
该语句执行时需要读取行数,数越小越好。如下图:
11、filtered
该语句返回结果的行数占读取行数的百分比,值越大越好。如下图:
12、extra
十分重要的额外信息。常见的如下:
1)、Distinct
MySQL发现第一个匹配的行后,停止为当前索引搜索更多的行。
2)、Not exists
MySQL能够对查询进行LEFT JOIN优化,发现1个匹配LEFT JOIN标准的行后,不再为前面的索引在该表内检查更多的行。
3)、Using filesort
MySQL 对数据使用一个外部的文件内容进行了排序,而不是按照表内的索引进行排序读取。如下图:
4)、Using index
仅使用索引树中的信息从表中检索列信息,而不必另外寻找读取实际行,即不需要回表。如下图:
5)、Using temporyary
在查询时,MySQL需要创建一个临时表来保存结果。常出现使用GROUP BY和ORDER BY子句时。如下图:
6)、Using where
在查找使用索引的情况下,需要回表去查询所需的数据,后再用WHERE子句完成结果过滤,通常出现这种情况的话就需要添加合适的索引来做优化了。如下图:
7)、Using join buffer
连接中的表分成几部分读入连接缓冲区,然后从缓冲区中使用它们的行来与当前表执行连接。如下图:
以上是关于MySQL中SQL语句的执行计划,你理解了吗?的主要内容,如果未能解决你的问题,请参考以下文章