在开发过程中,对每个上线的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. JavaScript Patterns 3.1 Object Literal

    Basic concept Values can be properties: primitives or other objects methods: functions User-defined ...

  2. mmap 与 read/write

    mmap与read/write两条路线对文件的访问比较 我们知道无论是通过mmap或read/write访问文件在内核中都必须经过缓存, 当需要从文件读写内容时,都经过内存拷贝的方式与内核中的缓存进行 ...

  3. 问题解决——OpenGL超级宝典 关于gltDrawTorus的错误解决

    看OpenGL超级宝典的时候,遇到一个函数 “gltDrawTorus”,在TRANSFORM和SPHEREWORLD中都有用到.但是一开始在自己写示例代码里时却没法使用,而在作者的代码目录结构下却可 ...

  4. java使用httpcomponents 上传文件

    一.httpcomponents简介 httpcomponents 是apache下的用来负责创建和维护一个工具集的低水平Java组件集中在HTTP和相关协议的工程.我们可以用它在代码中直接发送htt ...

  5. linux搭建一个配置简单的nginx反向代理服务器 2个tomcat

    1.我们只要实现访问nginx服务器能跳转到不同的服务器即可,我本地测试是这样的, 在nginx服务器里面搭建了2个tomcat,2个tomcat端口分别是8080和8081,当我输入我nginx服务 ...

  6. 【分享】iTOP-4412开发板使用之初体验[多图]

    近期入手了4412开发板,配的7寸屏和WIFI模块,GPS模块,下面晒个照片介绍一下,手机拍摄图片有点模糊,实物很精致,是我所见过最好的板子.b( ̄▽ ̄)d 预装的Android4.0.3系统,5点以 ...

  7. Linux shell get random number

    the Shell Profile: When a new interactive shell is started, /etc/profile, followed by /etc/bash.bash ...

  8. NOIP2008普及组传球游戏(动态规划)——yhx

    题目描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着同学们一起做传球游戏. 游戏规则是这样的:n个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球,每个同 ...

  9. HDU 4930 Fighting the Landlords --多Trick,较复杂模拟

    题意:两个人A和B在打牌,只有题目给出的几种牌能出若A第一次出牌B压不住或者A一次就把牌出完了,那么A赢,输出Yes,否则若A牌没出完而且被B压住了,那么A输,输出No. 解法:知道规则,看清题目,搞 ...

  10. [转]比较Jmeter、Grinder和JAVA多线程本身压力测试所带来的性能开销

    1. 测试环境 jmeter版本 :jmeter 2.4 grinder的版本 : Grinder 3 JAVA的版本:JDK 1.6 2. 测试代码 Jmeter测试代码 public class  ...