MySQL中SQL执行计划详解

MySQL执行计划是sql语句经过查询优化器后,查询优化器会根据用户的sql语句所包含的字段和内容数量等统计信息,选择出一个执行效率最优(MySQL系统认为最优)的执行计划,然后根据执行计划,调用存储引擎提供的接口,获取数据。

但是,在MySQL执行的时候,到底使用了一个什么样的执行计划,有没有用到索引。当数据规模比较大的时候,sql执行的时候,执行计划不同,会直接影响sql的执行速度。这个时候,就需要对sql语句执行进行调试。

MySQL我们在调试sql语句的时候,不会像我们写Java或者其他语言代码那样通过打断点的方式进行代码调试。这个时候,我们就需要通过查看执行计划来调试我们的sql了。MySQL通过EXPLAIN来查看执行计划,我们写sql语句的时候,在语句之前加一个EXPLAIN就可以了。EXPLAIN可以用在SELECT、DELETE、INSERT、PEPLACE以及UPDATE等语句中,如:

EXPLAIN SELECT
    *
FROM
    school
WHERE
    school_nick = '县第一小学'

EXPLAIN SQL

执行后,结果如下:

  这里介绍下每个字段以及每个字段的含义:

  id

  id是执行计划的标识符,是SELECT 查询的序号。如果结果集会跟其他表的结果用UNION关键字相结合,那么id可能为空。

  id是否为空,对执行计划的影响不大。

  select_type

  select_type表示sql语句查询的类型。具体表示如下表:

select_type的值            含义  
SIMPLE   简单的select查询,没有使用关联和子查询。  
PRIMARY   最外层select,包含子查询的时候,最外层的查询  
UNION   在一个UNION查询中,第二次或以后的子查询操作  
DEPENDENT UNION   在一个UNION查询中,第二次子查询或以后的SELECT查询的时候需要依赖外部的查询                           
UNION RESULT   UNION的返回结果集  
SUBQUERY   子查询语句的第一个select语句  
DEPENDENT SUBQUERY                                    依赖外部查询的第一个子查询  
DERIVED   派生表——该临时表是从子查询派生出来的,位于form中的子查询  
MATERIALIZED   物化子查询(不确定啥意思,以后研究后再回来补充,或者大神指教)  
UNCACHEABLE SUBQUERY        无法缓存结果的子查询,必须为外部查询的每一行重新计算  
UNCACHEABLE UNION   UNION中的第二个或以后的不可缓存的子查询。  

  table


  输出行引用的表的名称。一般为表格名称或别名,也可能为如下值:

  1.UNION的并集结果集。

  2.derivedN当前行指向派生结果集。可能是一个派生表,例如来自FROM子句的结果集。

  3.subqueryN 当前行指向一个子查询的结果集。

  type


  连接类型。该列输出表示如何连接表。下面的类型表示从最好的到最坏的类型

  1.system 该表只有一行(=系统表)。这是const连接类型的特例 。

  2.const 最多只有一行匹配,在查询开始的时候,计算出常量对应的地址,直接访问,例如:select * from test where  name ='zhang' 当name是唯一索引的时候,就有可能出现const。const非常快,因为它只读一次。

  3.eq_ref 除了 system和 const类型之外,这是最好的连接类型。当两个表联查时使用索引的所有部分(针对的是组合索引),且索引是 主键或唯一索引时使用它。使用“=”运算符来进行索引列的比较。

  4.ref 非唯一索引扫描,返回某个匹配值的所有行。常用语非唯一索引。这里对于eq_ref 和ref不熟悉的同学,可以看以下代码:

-- 给test表的name字段加唯一索引,test2 的job 行添加非唯一索引。
-- 这个代码执行后,首先执行test2 的查询,查出job = ‘teacher’ 的所有集合。
-- 所以test2 的typ是ref 表示的是匹配job = ‘teacher’ 的一个结果集。
-- 然后从结果集中取出name的集合,去匹配test1.name的结果。因为test1.name是唯一索引,所以一个name最多匹配到一条记录,所以test的type是ref
EXPLAIN SELECT
    *
FROM
    test,
    test2
WHERE
    test. NAME = test2. NAME
AND test2.job = '33'

test ref and eq_ref

执行结果如下图:

  5.fulltext 使用fulltext 索引进行查询。

  6.ref_or_null 这种链接类型类似于ref,但是,除了ref之外,还对包含null的值进行了搜索。常用于解析子查询。代码示例如下:

SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;

  7.index_merge 这个链接类型表示使用索引合并优化。输出内容包含在索引列表中。

  8.unique_subquery 索引查找,替换子查询,以提高效率。

value IN (SELECT primary_key FROM single_table WHERE some_expr)

  9. index_subquery 类似于unique_subquery 但是替换in子查询,适用于非唯一索引,代码: value IN (SELECT key_column FROM single_table WHERE some_expr)

  10.range 扫描部分索引,对索引的扫描从某一点开始,返回的是某个索引区域的值。常见的有基于索引的 < ,> 等的查询。

  11. index 扫描全部索引,对索引进行整体扫描。

  12.all 全表扫描,最慢的查询 。应该避免

 possible_keys

  可能使用的key,指出当前查询涉及到的行都含有那些索引。如果有索引就会列出,但是不一定会被使用。

  key

  实际使用的索引。如果没有使用索引,显示null。

  key_len

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/db3767ac9ce8aca42d6d885fb089f266.html