继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

MySql 执行计划

蝴蝶不菲
关注TA
已关注
手记 372
粉丝 81
获赞 381

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

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

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

复制代码

1 EXPLAIN SELECT2     *3 FROM4     school5 WHERE6     school_nick = '县第一小学'

复制代码

EXPLAIN SQL

  执行后,结果如下:


https://img3.mukewang.com/5b972be90001b3fe09470074.jpg

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

  id

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

  id是否为空,对执行计划的影响不大,如果有兴趣可以看另外一篇博客:mysql执行计划id为空—UNION关键字,这里不再赘述。

  select_type

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

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

  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不熟悉的同学,可以看以下代码:

  

复制代码

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

复制代码

test ref and eq_ref

 

  执行结果如下图:

  https://img4.mukewang.com/5b972bf20001dc9409350095.jpg

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

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

1 SELECT * FROM ref_table2   WHERE key_column=expr OR key_column IS NULL;

ref_or_null

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

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

value IN (SELECT primary_key FROM single_table WHERE some_expr)

unique_subquery

  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

  表中对应的索引最大可能长度。可以通过设置索引长度改变该值。例如:一个varchar(255)的索引长度为255,可是我们使用不到那么长,我们可以取字符串的前五位作为索引。这时key_len 就是5.这里关于索引值的长度的选取规则,以后有机会再写一篇博客详细介绍。

  ref

  哪些字段和key一起被使用。没用过。

  rows

  受影响的行数。不是特别精确的。

  Extra

  解释额外的信息。包含mysql对于query优化的时候的一些附加信息。非常有用。可能出现的结果如下:

  • const row not found 该表为空

  • Deleting all rows   表格内数据被标记删除,正在删除中(某些存储引擎支持一种方法,以简单快捷的方式删除所有行,这时查询就会出现这个提示)

  • Distinct  MySQL正在寻找不同的值,因此它在找到第一个匹配行后停止为当前行组合搜索更多行。

  • FirstMatch(tbl_name) 半连接FirstMatch连接快捷方式策略用于tbl_name

  • Full scan on NULL key当优化程序无法使用索引查找访问方法时,子查询优化将作为回退策略发生。

  • Impossible HAVING该HAVING子句始终为false,无法选择任何行。

  • Impossible WHERE 该WHERE子句始终为false,无法选择任何行。

  • Impossible WHERE noticed after reading const tables MySQL已经读取了所有 const(和 system)表,并注意到该WHERE子句始终为false。

  • No matching min/max row 没有行满足查询的条件的行

  • no matching row in const table  对于具有连接的查询,有一个空表或没有满足唯一索引条件的行的表。

  • No matching rows after partition pruning  对于DELETE或 UPDATE,优化器在分区修剪后发现没有删除或更新的内容。

  • No tables used 查询没有FROM子句

  • Not exists 查询的内容不存在 

  • Plan isn't ready yet 优化程序尚未完成为在命名连接中执行的语句创建执行计划时, 会出现此值。

  • Range checked for each record MySQL发现没有好的索引可以使用,但发现在前面的表的列值可能会使用某些索引。

  • Recursive  递归

  • Skip_open_table, Open_frm_only, Open_full_table  

    • Skip_open_table:表文件不需要打开。该信息已从数据字典中获得。

    • Open_frm_only:只需要读取表信息的数据字典。

    • Open_full_table:未优化的信息查找。必须从数据字典中读取表信息并读取表文件。

  • unique row not found  对于查询,没有行满足 索引或表的条件。

  • Using filesort  使用文件排序。MySQL必须执行额外的传递以找出如何按排序顺序检索行。排序是通过根据连接类型遍历所有行并将排序键和指针存储到与该WHERE子句匹配的所有行的行来完成的。然后对键进行排序,并按排序顺序检索行

  • Using index 仅使用索引树中的信息从表中检索列信息,而不必另外寻找读取实际行。当查询仅使用属于单个索引的列时,可以使用此策略。

  • Using index condition  通过首先访问索引,确定是否可以读取完整的表行。

  • Using index for group-by  使用索引分组。表示MySQL找到了一个索引,可用于检索GROUP BY或 DISTINCT查询的所有列,而无需对实际表进行任何额外的磁盘访问。此外,索引以最有效的方式使用,因此对于每个组,只读取少数索引条目。

  • Using index for skip scan  使用索引跳过扫描范围

  • Using join buffer  将表数据读入缓存,然后从缓存中读数据来执行操作。

  • Using MRR 使用多范围读取优化策略读取表。

  • Using temporary 使用临时表,MySQL需要创建一个临时表来保存结果。如果查询包含以不同方式列出列的GROUP BY和 ORDER BY子句,则通常会发生这种情况。

  • Using where  使用上了where限制,表示MySQL服务器在存储引擎受到记录后进行“后过滤”(Post-filter),如果查询未能使用索引,Using where的作用只是提醒我们MySQL将用where子句来过滤结果集。

  • Zero limit  查询有一个LIMIT 0子句,不能选择任何行。

  • Only index  这意味着信息只用索引树中的信息检索出的,这比扫描整个表要快。 

文章来源:http://www.cnblogs.com/liyasong/


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP