MySQL中SQL执行计划,你理解了吗

北京哪个医院白癜风比较好 http://pf.39.net/bdfyy/bdfzg/150615/4639333.html

首先我们来看一下什么是执行计划:

执行计划就是解释select语句如何在数据库执行的、相关表是怎么连接、连接的次序、有哪些索引和索引使用情况、每个表的扫描数据量等等。简单来说,就是通过数据来分析select语句的执行情况;

怎么查看执行计划:查看执行需要用到关键字EXPLAIN,将EXPLAIN放在SQL语句的前面(EXPLAIN[EXTENDED]SELECTselect_options),如下图:

从上图可以看出,通过执行计划展示了表格数据,这个表格有id、select_type、table、partitions、type、possible_keys、key、key_len、ref、rows、filtered、extra等字段的信息,这些字段分别表示什么意思呢?下面具体介绍下:

1、id

执行计划的id是select查询的序列号,标识执行顺序。注意有两种情况,具体如下:

1)、当id相同时,执行顺序从上到下执行。

左外连接,先执行左边后执行右边(例如:select*fromuseruleftjoincustom_ordercoonu.id=co.creater会先执行user表后执行custom_order),在执行计划中,user表应该在上面,custom_order在下面,如下图:

右外连接,先执行右边后执行左边(例如:select*fromuserurightjoincustom_ordercoonu.id=co.creater会先执行custom_order表后执行user表),在执行计划中,custom_order表应该在上面,user在下面,如下图:

从上面的执行结果来看,和预计的一样。

2)、当id不相同时,id越大越先执行。

例如:select*fromuserwhereid=(selectcreaterfromcustom_orderwhereid=1),这个语句中的子查询会比主查询会先执行。那在explainselect*fromuserwhereid=(selectcreaterfromcustom_orderwhereid=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)、DEPENDENTUNION

union中的第二个或后面的select语句,取决于外面的查询。如下图

5)、UNIONRESULT

union的结果。如下图

6)、SUBQUERY

子查询的第一个select语句。如下图

7)、DEPENDENTSUBQUERY

子查询中的第一个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。当使用=、、、=、、=、ISNULL、=、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)、Notexists

MySQL能够对查询进行LEFTJOIN优化,发现1个匹配LEFTJOIN标准的行后,不再为前面的索引在该表内检查更多的行。如下图:

3)、Usingfilesort

MySQL对数据使用一个外部的文件内容进行了排序,而不是按照表内的索引进行排序读取。如下图:

4)、Usingindex

仅使用索引树中的信息从表中检索列信息,而不必另外寻找读取实际行,即不需要回表。如下图:

5)、Usingtemporyary

在查询时,MySQL需要创建一个临时表来保存结果。常出现使用GROUPBY和ORDERBY子句时。如下图:

6)、Usingwhere

在查找使用索引的情况下,需要回表去查询所需的数据,后再用WHERE子句完成结果过滤,通常出现这种情况的话就需要添加合适的索引来做优化了。如下图:

7)、Usingjoinbuffer

连接中的表分成几部分读入连接缓冲区,然后从缓冲区中使用它们的行来与当前表执行连接。如下图:

这次的内容就到这里,欢迎大家在评论区评论!




转载请注明:http://www.aierlanlan.com/cyrz/2130.html