zoukankan      html  css  js  c++  java
  • MySQL阅读笔记——11.Explain详解

      MySQL经过 基于成本基于规则 的优化后生成 执行计划 ,通过在语句前面加上Explain关键字可以查看执行计划:

    列名描述
    id 在一个大的查询语句中每个SELECT关键字都对应一个唯一的id
    select_type SELECT关键字对应的那个查询的类型
    table 表名
    partitions 匹配的分区信息
    type 针对单表的访问方法
    possible_keys 可能用到的索引
    key 实际上使用的索引
    key_len 实际使用到的索引长度
    ref 当使用索引列等值查询时,与索引列进行等值匹配的对象信息
    rows 预估的需要读取的记录条数
    filtered 某个表经过搜索条件过滤后剩余记录条数的百分比
    Extra 一些额外的信息

     

    id

    • 查询语句每出现一个select语句,MySQL就会为它分配一个唯一id这个id作为explain第一列

    • 连接查询时每个表都会对应explain中id相同的一条记录

    • 子查询中每个select语句都会对应一个explain中的 唯一id

    • 如果查询优化器对子查询语句进行重写转换为 连接查询 ,则在explain结果中的记录id全部相同

    • union会对结果集去重,explain结果集会在原select语句基础上多出id为null的 临时表 记录

    Explain每一条记录是一中查询,id相同的多条记录是连接查询(或者是能转换成连接查询的子查询),id不同的多条记录是子查询嵌套

    select_type

    • SIMPLE:不包含unionunion all子查询 的查询都算SIMPLE,连接查询也算SIMPLE

    • PRIMARY:包含union union all或者子查询的大查询,最左边的查询就是PRIMARY

    • UNION:包含union union all或者子查询的大查询,除去最左边的查询其余小查询是UNION

    • UNION RESULT:使用临时表完成union去重工作

    • SUBQUERY:子查询不是相关子查询并且不能转换为semi-join(半连接)并且查询优化器使用 物化 方案执行该子查询,则该子查询的第一个select语句就是SUBQUERY,(由于该类型子查询会被物化,所以只会执行一遍)

    • DEPENDENT SUBQUERY:子查询是相关子查询并且不能转换为semi-join(半连接),则该子查询的第一个select语句就是SUBQUERY SUBQUERY

    • DEPENDENT UNION:子查询是unionunion all并且都依赖外层查询,则该子查询中除了最左边的第一个查询,其余小查询都是DEPENDENT UNION

    • DERIVED:物化 后派生表(from语句后的子查询)对应的 直接查询(派生表不一定 物化,还有可能与外层查询合并)

    • MATERIALIZED:将 子查询物化 后与外层查询进行 连接查询 ,该子查询类型就是MATERIALIZED

    • UNCACHEABLE SUBQUERY 和 UNCACHEABLE UNION:不常用

    type

    • system:当表只有一条记录并且表的存储引擎统计数是精确的,如MyISAM、Memory(InnoDB是ALL)

    • const:根据 主键 或者 唯一二级索引 与常数列等值匹配

    • eq_ref:连接查询 被驱动表 通过 主键唯一二级索引 列等值匹配访问(如果被驱动表的主键或唯一二级索引是 联合索引 ,则 联合索引的所有列 必须等值比较)

    • ref:通过 普通二级索引 与常量进行等值匹配来查询某个表

    • ref_or_null:通过 普通二级索引 与常量进行等值匹配并且查询条件指定该列值可以是 NULL 来查询某个表

    • index_merge:以IntersectionUnionSort-Union三种索引合并的方式执行查询(就是将查询条件中用到每个条件进行查询,将结果集(主要是主键)进行 交集并集并集-排序 操作,之后再进行 回表 或者直接返回结果(查询结果覆盖索引))

    • unique_subquery:查询优化器将 IN子查询 转换为 EXISTS查询 并且子查询用到 主键 或者 唯一二级索引 等值匹配(IN相关子查询),执行该计划的子查询type就是unique_subquery

       EXPLAIN SELECT * FROM s1 WHERE key2 IN (SELECT id FROM s2 where s1.key1 = s2.key1) OR key3 = 'a';
      +----+--------------------+-------+-----------------+------------------+
      | id | select_type       | table | type           | possible_keys   |
      +----+--------------------+-------+-----------------+------------------+
      |  1 | PRIMARY           | s1   | ALL             | idx_key3         |
      |  2 | DEPENDENT SUBQUERY | s2   | unique_subquery | PRIMARY,idx_key1 |
      +----+--------------------+-------+-----------------+------------------+
    • index_subquery:查询优化器将 IN子查询 转换为 EXISTS查询 并且子查询用到是 普通索引

    • range:在索引上使用范围查询(IN查询可以看作是单点区间)

    • index:结果集覆盖索引,但要扫描全部索引记录(查询条件中不符合联合索引 最左匹配原则 没有使用到索引,但是结果列是索引列不用 回表

    • ALL:没用到任何索引,全表扫描

    除了index_merge之外,所有访问方法最多只用到一个索引

    possible_keys和key

    • possible_keys:表示可能查询用到的索引

    • key:表示查询实际用到的索引

    possible_keys越多表示查询优化器计算成本耗时越多,因此尽量删除不需要的索引

    使用index访问,possible_keys是NULL,而key是查询涉及的索引(联合索引)

    key_len

    • 索引列如果是固定长度类型就是固定值,如果是变长字符集(如:utf8)就是最大存储空间

    • 如果该列可以为NULL,则比不可以存储NULL值多1字节

    • 变长索引字段会使用2字节存储实际长度(之前说过使用1~2字节,此处统一为2字节)

    ref

    当使用索引列等值匹配的条件去执行查询时,也就是在访问方法是consteq_refrefref_or_nullunique_subqueryindex_subquery其中之一时,ref展示的是与索引列等值匹配的值,可能是const代表一个常数,可能是连接查询的另一个表主键,可能是函数(ref列为func)

    rows

    如果全表扫描就代表 预估 的扫描行数,如果使用索引执行计划,就代表 预估 执行计划扫描的 索引记录行数

    filtered

    • 如果使用索引执行扫描,则filtered列代表代表除去使用到索引条件外,满足其他条件的记录占比是多少(扇出数=filtered%*rows)

    • 如果是全表扫描,则计算扇出时满足条件的记录数

    Extra

    • No tables used:查询语句没有from语句

    • Impossible WHERE:where子句永远为false

    • No matching min/max row:使用MIN或者MAX函数覆盖二级索引,但没有符合where条件的记录

    • Using index:当 查询条件搜索条件 只包含某个索引列,即覆盖索引(不需要 回表

    • Using index condition:索引条件下推(MySQL5.6新增)无法利用到索引的where条件(但是在索引中存储了该值)会在 回表 之前进行过滤,如:where中使用了like '%xxx'匹配联合索引的另外字段

    • Using where:使用全表扫描,并且where中有搜索条件(未使用到索引)

    • Using join buffer:连接查询,对 被驱动表 的访问不能有效利用索引,则会分配一块名叫join buffer的内存块加快查询速度

    • Not exists:连接查询,where要求 被驱动表 某列等于NULL,而那个列又不允许为NULL

    • Using intersect(...)、Using union(...)和Using sort_union(...):该查询在括号内的列上进行了索引合并

    • Zero limit:LIMIT子句参数为0

    • Using filesort:order by无法使用到索引,只能在内存或者磁盘进行排序

    • Using temporary:如果不能有效利用索引,会借助临时表(MySQL会在group by查询后默认添加order by,如果不想在group by后执行排序,要手动设置order by null

    • Start temporary, End temporary:查询优化器将IN查询转化为semi-join通过DuplicateWeedout策略建立临时表对外层查询记录去重,则驱动表为Start temporary,被驱动表为End temporary

    • LooseScan:将IN查询转化为semi-join通过LooseScan策略,驱动表的执行计划

    • FirstMatch(tbl_name):将IN查询转化为semi-join通过FirstMatch策略,被驱动表的执行计划

    通过在查询语句前面加上explain format=json可以看到语句的执行成本

    在使用explain语句后紧接着通过show warnings可以查看查询计划的扩展信息,当Code为1003时,Message展示的是不标准的 查询优化器重写 后的语句

    optimizer trace在MySQL5.6之后新增的用来查看 查询优化器 执行的整个过程,通过设置系统变量set optimizer_trace="enabled=on";来开启,通过SHOW VARIABLES LIKE 'optimizer_trace';来查看是否开启了该功能(默认关闭),开启后执行查询语句后可以通过SELECT * FROM information_schema.OPTIMIZER_TRACE查看优化器的具体执行过程,主要分成 prepareoptimizeexecute 三个阶段,基于成本的优化主要集中在 optimize 阶段,单表查询在 optimize 阶段的 rows_estimation过程,多表连接查询在considered_execution_plans过程


  • 相关阅读:
    BestCoder6 1002 Goffi and Squary Partition(hdu 4982) 解题报告
    codeforces 31C Schedule 解题报告
    codeforces 462C Appleman and Toastman 解题报告
    codeforces 460C. Present 解题报告
    BestCoder3 1002 BestCoder Sequence(hdu 4908) 解题报告
    BestCoder3 1001 Task schedule(hdu 4907) 解题报告
    poj 1195 Mobile phones 解题报告
    二维树状数组 探索进行中
    codeforces 460B Little Dima and Equation 解题报告
    通过Sql语句控制SQLite数据库增删改查
  • 原文地址:https://www.cnblogs.com/leon618/p/13783329.html
Copyright © 2011-2022 走看看