在开发过程中,对每个上线的SQL查询指纹(query figerprint)的质量都应有估算;而估算DB查询质量最直接的方法,就是分析其查询执行计划( Query Execution Plan ,即QEP)。
MySQL数据库,通过Explain指令查看SELECT(5.6.3+版本开始支持update/delete/insert等),下图为sakila.actor的表结构和一个主建过滤查询的执行计划。

本文细说从以下三个方面:
1.如何读取EXPLAIN的输出结果
2.简介MySQL5.6的 EXPLAIN FORMAT = JSON和MySQL Workbench的Visual Explain
3.简介MySQL的CBO和Optimizer Trace


如何读取EXPLAIN的输出结果

EXPLAIN的输出一般12个字段(其中partitions和filtered 5.5版本普通模式下没有),会对重要的字段内容进行分析说明

本节详细分析,每个字段的含义和使用。

id字段

表示SELECT查询标识符,用于标识执行顺序,基本是数字;
执行顺序原则:id数据值大的优先执行,id值相同的从上往下顺序执行; 上图id值都为1,故SQ先执行actor表的查询

select_type字段

表示select子句的类型,常值有:
SIMPLE: 简单查询,查询子句不包含UNION或子查询
PRIMARY:最外层的SELECT子句
UNION: UNION子句右侧的SELECT子句
SUBQUERY: 子查询中第一个SELECT
DERIVED: 衍生表的SELECT子句

table字段

表示查询涉及的表或衍生表; 图2中:第一行操作的actor表的查询,第二行操作是file_actor表的查询;

partitions字段:

针对MySQL内置分区表,表示当前使用了哪些子分区;用于确认查询对分区的过滤效率

type字段[重要]

表示查询的access type,表示查询是否为”全表扫描“,”索引扫描“等
常见以下几种类型,查询效率由最差到最好
all<index<range ~ index_merge< ref<eq_ref<const<system(效率理论从最差到最好)
详细说明每种常见type表示的含义

  • 5.1 ALL 表示”全表扫描”(full table scan), 性能是最差的几种查询之一,如果查询的表比较大,且查询频次高,对MySQL数据库有致命的性能影响。
    见下图:因last_update字段没有索引,帮整体是全表扫描, 扫描rows 200条
  • 5.2 index 表示“全索引扫描”(full index scan),其类型和ALL较类似,性能也是比较差; 和ALL区别在于只对索引树进行扫描,但索引没有起到过滤作用。
  • 5.3 range 表示“索引范围扫描”, 通过索引字段范围获取表中部分数据记录; 常常用于in,>,< between等操作,查询效率一般不错。 下图rows只扫描了4行数据,就获取到指定数据
  • 5.4 index_merge MySQL查询优化器发现查询可以同时使用多个索引查询结果集进行并集或交集的情况,就会使用index_merge type。
    此时key字段有两个或多个索引, key_len/rows都分别有两个数值; 如果是并集操作”Using intersect”, 往往通过两个索引的字段,合并为一个索引,避免index_merge查询
    下图中两个SQL一个是AND/OR, Using intersect 和Using union 分别表示使用两个索引后的交集和并集
  • 5.5 ref 针对于非唯一或主键索引,或使用二者”最左部分字段”索引的等值查询或多表join,查询效率由这个值返回的行数多少决定
  • 5.6 eq_ref 使用于多表的join时,被驱动表的过滤字段是主键或唯一索引,查询效率很好
  • 5.7 const 针对主键或唯一索引的等值查询扫描,最多只返回一行数据
  • 5.8 system: 是一种特殊const类型,被查询表中有且只有一条数据

    possible_keys字段

    表示MySQL查询优化器发现当前查询可能被使用地索引,但不一定能会利用,如果possible_key的列举的索引越多,往往说明索引创建不合理,查询效率不是最高效;
    因为优化器会分析尽可能多的索引,评估哪个索引的“成本”消耗局部最低,这个评估过程消耗时间和资源的。

    key 字段[重要]

    表示查询优化器真正使用的索引(可能多个,如前index_merge), 如果是索引覆盖,那么索引不会在possible_keys中出现的; 注意:对于组合索引,查询可能只使用其部分字段,详细见下面key_len计算分析

    key_len字段[重要]

    表示查询优化器使用了索引的字节数,可以评估组合索引是否完全被使用,或只有最左部分字段使用
    key_len字节的计算规则:

  • 字符串:char(n) - n字节, varchar(n)- n字节 + 2字节(变长), , 多字节charset * [1~4]字节(utf8为3字节,utf8mb4为4字节计算)
  • 数值类型: TINYINT-1字节,SMALLINT-2字节, MEDIUMINT-3字节, INT-4字节,BIGINT-8字节
  • 时间类型:DATE-3字节, TIMESTAMP-4字节, DATETIME-8字节
  • 字段属性:NULL属性+ 1字节
    计算demo:
    下图两个SQL使用相同的索引,但索引的效果和key_len却分别是9字节和119字节
    SQL1 key_len计算: pay_user_id字段8字节(bigint not null) + product_type字段 1个字节 = 共9个字节, 说明SQL1只使用了idx_userid组合索引的前2个字段,product_id字段未使用,过滤性不太好。
    SQL key_len计算: 前两字段9字节+ product_id字段110字节 ( varchar(36) utf8字符集和2字节变长, 36*3+2为110字节) = 9 + 110=119字节, SQL2使用了前三个字段,过滤性较好

    rows 字段[重要]

    MySQL查询优化器根据统计信息,估算SQL要查找到结果集需要扫描读取的数据行数; 这个值非常直观显示SQL的效率好坏,原则rows越少越好。
    后文会计划的优化器的cost估算时,ROW_EVALUATE_COST就是扫描1行数据,算0.2

Extra字段[重要]

MySQL执行计划很多额外的信息在Extra字段显示,常见的有以下几种内容

  • 10.1 Using filesort
    MySQL需额外的排序操作,不能通过索引顺序达到排序效果;又叫”文件排序“,易错误理论为排序结果过大,内存中不够需写磁盘文件排序。
    一般有filesort,都建议优化去掉,CPU资源消耗大。 下图last_update排序,但此字段无索引,故需filesort
  • 10.2 Using index
    ”覆盖索引扫描“,表示查询在索引树中就可查找所需数据,不用回表数据文件(回表操作),往往说明性能不错
  • 10.3 Using temporary
    查询有使用临时表,一般出现于排序,分组和多表join的情况,查询效率不高,建议优化

简介EXPLAIN FORMAT=JSON 和 MySQL Workbench的Visual Explain

EXPLAIN FORMAT=JSON

从MySQL5.6,支持JSON格式的输出;输出的结果信息更详细,针对复杂查询的执行计划结构顺序更加清晰
explain format=json select f.film_id, f.title, c.name from film f inner join film_category fc on f.film_id=fc.film_id inner join category c on fc.category_id = c.category_id where f.title like ‘B%’;

MySQL Workbench的Visual Explain

MySQL Workbench的Visual Explain
执行计划的读取是:从左往右,从下往上

简介MySQL的CBO和Optimizer Trace

从MySQL5.6版本开始,可支持把MySQL查询执行计划树打印出来,对DBA深入分析SQL执行计划,COST成本都非常有用,打印的内部信息比较全面;
功能支持动态开关,因为对性能有20%左右影响,只建议分析问题时,临时开启
1 使用方式 set session optimizer_trace= “enabled=on”; 然后执行你要分析的SQL, 再执行SELECT trace FROM information_schema.OPTIMIZER_TRACE;就可查看SQL的Optimizer Trace信息
DEMO:
set session optimizer_trace= “enabled=on”;
select from actor ;
SELECT trace FROM information_schema.OPTIMIZER_TRACE\G
使用场景举例:计算评估查询的“成本” CBO
MySQL优化器通过计算每种可能计划的“成本”,最终选择“成本”最小的作为执行计划。
MySQL查询优化器都是Cost Model包含两个模型IO和CPU
以下为Table scan的情况的IO计算公式,用于验证 Optimizer Trace的cost-info是否一致
IO Cost : 读取的table/index的页个数 
O_BLOCK_READ_COST #其中O_BLOCK_READ_COST常量为1
CPU Cost: 读取行数 rows ROW_EVALUATE_COST #其中ROW_EVALUATE_COST常量为0.2
计算 select 
from actor 这个查询的执行计划cost-info:
通过 select from mysql.innodb_index_stats where table_name =’actor’ and stat_name=’size’; 获取这次表扫描primary只有1个page,rows为200行
总体cost = io-cost+cpu-cost = 1 pages 
O_BLOCK_READ_COST + 200 rows ROW_EVALUATE_COST= 11 + 200 * 0.2 = 41
和图中”best_access_path”中cost值41相匹配。(当然MySQL在Range,join等复杂SQL的查询分析,相当复杂,这里只是举例说明trace输出信息的强大)
输出结果如下图:

 

[转]细说MySQL Explain和Optimizer Trace简介的更多相关文章

  1. 【MySQL】使用 Optimizer Trace 观察SQL执行过程

    Optimizer Trace 是MySQL 5.6.3里新加的一个特性,可以把MySQL Optimizer的决策和执行过程输出成文本.输出使用JSON格式,便于程序分析和人类阅读. 使用方法 1) ...

  2. 100% 展示 MySQL 语句执行的神器-Optimizer Trace

    在上一篇文章<用Explain 命令分析 MySQL 的 SQL 执行>中,我们讲解了 Explain 命令的详细使用.但是它只能展示 SQL 语句的执行计划,无法展示为什么一些其他的执行 ...

  3. [MySQL 5.6] 初识5.6的optimizer trace

      在MySQL5.6中,支持将执行的SQL的查询计划树记录下来,目前来看,即使对于非常简单的查询,也会打印出冗长的查询计划,看起来似乎不是很可读,不过对于一个经验丰富,对查询计划的生成过程比较了解的 ...

  4. MYSQL EXPLAIN执行计划命令详解(支持更新中)

    本文来自我的github pages博客http://galengao.github.io/ 即www.gaohuirong.cn 摘要: 本篇是根据官网中的每个一点来翻译.举例.验证的:英语不好,所 ...

  5. mysql explain优化

    简介 MySQL 提供了一个 EXPLAIN 命令, 它可以对 SELECT 语句进行分析, 并输出 SELECT 执行的详细信息, 以供开发人员针对性优化.EXPLAIN 命令用法十分简单, 在 S ...

  6. mysql explain type详解

    本文转载自最官方的 mysql explain type 字段解读 读了很多别人的笔记都杂乱不堪,很少有实例,什么都不如原装的好,所以当你读到我的笔记的时候如果觉得说的不明白,最好参考官方的手册. 我 ...

  7. 细说MySQL连接查询:内连、左连和右连

    转: 细说MySQL连接查询:内连.左连和右连 简介: MySQL 的连接查询,通常都是将来自两个或多个表的行结合起来,基于这些表之间的共同字段,进行数据的拼接.首先,要确定一个主表作为结果集,然后将 ...

  8. MySQL explain结果Extra中"Using Index"与"Using where; Using index"区别探究

    问题背景 最近用explain命令分析查询sql执行计划,时而能看到Extra中显示为"Using index"或者"Using where; Using Index&q ...

  9. 【转载】 mysql explain用法

    转载链接:  mysql explain用法 官网说明:     http://dev.mysql.com/doc/refman/5.7/en/explain-output.html 参数:  htt ...

随机推荐

  1. TCP 连接的 TIME_WAIT 过多 导致 Tomcat 假死

    最近系统二次开发之后,发现使用的 Tomcat 7 会经常假死.前端点击页面无任何反应,打开firebug,很多链接一直在等待服务器的反应.查看服务器的状态,CPU占用很少,最多不超过10%,一般只有 ...

  2. [转]Linux下权限掩码umask

    本文转自:http://www.cnblogs.com/123-/p/4188942.html ---------------------------------------------------- ...

  3. 详细的图文教程来实现 eclipse环境下如何配置tomcat,并且把项目部署到Tomcat服务器上

    很多初学,尤其自学JavaWeb的朋友首次在eclipse下配置tomcat时,总会有种难下手的感觉,在此,通过图文解说的方法,最直观的向大家演示一遍该配置过程. 第一部分:eclipse环境下如何配 ...

  4. 烂泥:centos6.4服务器添加新硬盘

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 公司FTP服务器的空间又不够了,唉,没有办法只能新加硬盘了.因为以前没有给Linux服务器添加过硬盘,所以只能先在虚拟机中进行模拟. 新加硬盘的操作步骤 ...

  5. 制作nginx和php的rpm包

    rpm包的制作真几把烦,制作php的rpm花了我3天时间,因为是根据线上环境来做的,依赖的第三方库太多,本来想把所有的第三方库做进php包,后来发现在rpmbuild -bb的时候非常耗时,而且乱七八 ...

  6. sigemptyset,sigfillset,sigaddset,sigdelset,sigismember,sigprocmask,sigpendmask作用

    SYNOPSIS #include <signal.h> int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); in ...

  7. uva133-S.B.S.

    The Dole Queue  In a serious attempt to downsize (reduce) the dole queue, The New National Green Lab ...

  8. hdu 5802 Windows 10 贪贪贪

    传送门:hdu 5802 Windows 10 题意:把p变成q:升的时候每次只能升1,降的时候如果前一次是升或者停,那么下一次降从1开始,否则为前一次的两倍 官方题解: 您可能是正版Windows ...

  9. 【转】dsadd user批量创建AD用户命令详解

    常见的批量创建用户的方法有四种: 一. 帐户模板的方式 二. CSVDE和LDIFDE 三. 脚本的方式 四. DSADD 但是很少有详细的资料使用DSADD的方式来批量创建帐户,那么我就把我近期使用 ...

  10. java GUI,贷款服务器

    本习题来自<java语言程序设计--进阶篇>第30章,网络编程的习题. 题目描述:为一个客户端编写一个服务器.客户端向服务器发送贷款信息(年利率.贷款年限和贷款总额).服务器计算月偿还额和 ...