• 高性能mysql 附录D explain执行计划详解


    EXPLAIN:

    • extended关键字:在explain后使用extended关键字,可以显示filtered列和warning信息。在较旧的MySQL版本中,扩展信息是使用EXPLAIN EXTENDED生成的。 该语法仍然被识别为向后兼容,但扩展输出现在默认启用,因此EXTENDED关键字是多余的,已被弃用。 它的使用会导致警告,并且将在未来的MySQL版本中从EXPLAIN语法中删除。
    • partitions关键字:显示查询将访问的分区,如果你的查询是基于分区表。

    在5.6版本,如果要获取filtered列和warning信息,还要加上extended关键字的。

    如:

    1. mysql> EXPLAIN EXTENDED
    2.        SELECT t1.a, t1.a IN (SELECT t2.a FROM t2) FROM t1G
    3. *************************** 1. row ***************************
    4.            id: 1
    5.   select_type: PRIMARY
    6.         table: t1
    7.          type: index
    8. possible_keys: NULL
    9.           key: PRIMARY
    10.       key_len: 4
    11.           ref: NULL
    12.          rows: 4
    13.      filtered: 100.00
    14.         Extra: Using index
    15. *************************** 2. row ***************************
    16.            id: 2
    17.   select_type: SUBQUERY
    18.         table: t2
    19.          type: index
    20. possible_keys: a
    21.           key: a
    22.       key_len: 5
    23.           ref: NULL
    24.          rows: 3
    25.      filtered: 100.00
    26.         Extra: Using index
    27. 2 rows in set, 1 warning (0.00 sec)
    28.  
    29. mysql> SHOW WARNINGSG
    30. *************************** 1. row ***************************
    31.   Level: Note
    32.    Code: 1003
    33. Message: /* select#1 */ select `test`.`t1`.`a` AS `a`,
    34.          <in_optimizer>(`test`.`t1`.`a`,`test`.`t1`.`a` in
    35.          ( <materialize> (/* select#2 */ select `test`.`t2`.`a`
    36.          from `test`.`t2` where 1 having 1 ),
    37.          <primary_index_lookup>(`test`.`t1`.`a` in
    38.          <temporary table> on <auto_key>
    39.          where ((`test`.`t1`.`a` = `materialized-subquery`.`a`))))) AS `t1.a
    40.          IN (SELECT t2.a FROM t2)` from `test`.`t1`
    41. 1 row in set (0.00 sec)

    SHOW WARNINGS中给出的是模拟执行计划的sql。里面有非常丰富的内容。可以提供给我们来参考。

    show warnings的说明:https://dev.mysql.com/doc/refman/5.7/en/explain-extended.html

    explain语法"尽量"不执行查询,但是如果为了获取执行计划需要查询(如要有子查询的结果才知道下一步的查询计划),那么explain其实是需要执行一些查询的。

    EXPLAIN只是一个近似结果。以下有一些相关的限制:

    • EXPLAIN不会告诉你触发器、存储过程或UDF会如何影响查询。
    • EXPLAIN 不支持存储过程,尽管可以手动抽取查询并单独对其进行EXPLAIN操作。
    • EXPLAIN不会告诉你MySQL在查询执行中所做的特定优化。
    • EXPLAIN不会显示关于查询的执行计划的所有信息。
    • EXPLAIN不区分具有相同名字的事物。例如,它对内存排序和临时文件都使用"filesort",并且对于磁盘上和内存中的临时表都显示"Using temporary"。

    重写非select查询

    explain只能解释select查询,无法解释存储过程、insertdeleteupdate等其他类似的语句,可以把非select语句转化为对等的 select 访问请求。

    ps5.6之后可以解释update insert

    EXPLAIN中的列:

    id

    id用来表示执行顺序,id相同的为一组,先执行id数字大的组,然后执行数字小的组。在id相同的一组内,顺序由上而下执行。子查询和union操作产生新的id,普通的join不会产生新id

    select type

    val

    explain

    SIMPLE

    简单 SELECT(不使用 UNION 或子查询)

    PRIMARY

    查询中包含任何复杂查询,最外层的的SELECT

    SUBQUERY

    select where 中包含的子查询

    DERIVED

    FROM 子句的子查询;

    Mysql会将这种子查询执行并放在一个临时表中。

    union 包含在 from 子句的子查询中,外层的 select被标记为 DERIVED

    UNION

    select where 中包含的子查询

    UNION RESULT

    UNION结果

    DEPENDENT UNION

    UNION 中的第二个或后面的 SELECT 语句,取决于外面的查询 DEPENDENT SUBQUERY

    DEPENDENT SUBQUERY

    子查询中的第一个 SELECT,取决于外面的查询

     ps:mysql5.6有MATERIALIZED,代表物化子查询

    type

    表示MySQL在表中找到所需行的方式,又称"访问类型",常见类型如下:

     

    由左至右,由最差到最好。

    ALL代表全表扫描(如果有limit,也会显示ALL,其实可能没有扫描全部的数据,扫描部分就停止了),

    index代表索引全扫描(一般出现在where中没有索引的条件,但是order by中有索引。),他的性能甚至不如ALL,因为ALL直接通过聚簇索引来获取数据,如果id是连续的,那么数据也是连续的,而index需要通过二级索引来检索id,然后在根据id检索数据,会产生大量io,使用这个一般是为了避免排序。

    range索引范围扫描(where中有索引的条件 如> between,或者in后面是固定的值,但是in和其他的有差别,in可以想象成是拆分成很多=),

    ref是非唯一性索引扫描,常见的是作用在=的比较上,但是非唯一

    eq_ref:ref的唯一性索引扫描。

    const, system: 当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量。system是const类型的特例,当查询的表只有一行的情况下, 使用system。

    5.6中还包含:

    ref_or_null:此连接类型与ref一样,但除此之外,MySQL还会对包含NULL值的行进行额外的搜索。

    如下SQ可以使用ref_or_null:

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

    index_merge:此连接类型表示使用索引合并优化。 

    unique_subquery:unique_subquery只是一个索引查找功能,可以完全替换子查询以提高效率。如:

    value IN (SELECT primary_key FROM single_table WHERE some_expr)

    index_subquery:此连接类型与unique_subquery类似。 它替换IN子查询,但它适用于以下形式的子查询中的非唯一索引。

    possible_keys

    指出MySQL能使用哪个索引在表中找到行,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用。注:如果使用覆盖索引扫描,此处为空。

    key

    显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL

    key_len

    表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度

    rows:

    表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数。如果三张表的join,那么将三行的rows相乘,就是数据库大概要读取的所有行数。

    ref:

    记录使用key列标识的索引时,查找值使用的常数或者列。

    extra列:

    use index:这里并不是表示使用了索引的意思。使用了索引可以通过key列来查看,而且key列显示了使用索引的名称。use index表示使用覆盖索引扫描。就是说,没有访问数据文件,所有的数据都是从索引文件中获取。

    use where:这里并不是表示使用了where条件的意思,而是说服务层从存储引擎获取数据之后再进行where过滤。

    Using index condition:表示使用索引条件下推。

    Using filesort:使用了排序(即使是内存中的排序也叫filesort)

    Using temporary:使用了临时表

    Impossible WHERE:出现在优化阶段,优化器根据表定义可以判断出where条件根本不可能成立,比如主健不可能为空

     Using join buffer (Block Nested Loop):mysql使用了优化过的nest loop算法,一次读取多个块.

    filtered 列

       

    这一列在使用EXPLAIN EXTENDED时出现。它显示的是针对表里符合某个条件(where子句或联接条件)的记录数的百分比所做的一个悲观估算。如果将rows列和这个百分比相乘,就能看到MySQL估算它将和查询计划里前一个表关联的行数。

    ps:如果filtered比例太大,那么mysql将会舍弃使用索引,而选择ALL。

    扩展:

    http://www.jianshu.com/p/fa37e037aa5f 有列子

    http://www.cnblogs.com/jxlwqq/p/5391232.html

     

  • 相关阅读:
    使用通配符查询
    使用聚合函数查询
    有趣的图标
    利用Office Chart 制作柱图(一个柱子)
    众多select
    对象不能从 DBNull 转换为其他类型。
    使用谓词进行查询
    使用数学函数查询
    学生信息表 通过选择年级和班级得到详细的学生信息名单
    使用时间函数查询
  • 原文地址:https://www.cnblogs.com/xiaolang8762400/p/6974048.html
Copyright © 2020-2023  润新知