zoukankan      html  css  js  c++  java
  • MySQL优化1之Explain详解

    1.Explain简介

    获取 select 语句的执行计划,通过 explain 我们可以知道:表的读取顺序,数据读取操作的类型,哪些索引可以使用,哪些索引实际使用了,表之间的引用,每张表有多少行被优化器查询等信息。

    样例:

    在 select 语句之前增加 explain 关键字,执行查询时,会返回执行计划的信息,而不是执行这条SQL(如果 from 中包含子查询,仍会执行该子查询,将结果放入临时表中)。

    mysql> explain select * from user;

    +----+-------------+-------+------+---------------+------+---------+------+------+-------+

    | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |

    +----+-------------+-------+------+---------------+------+---------+------+------+-------+

    |  1 | SIMPLE      | user | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |

    +----+-------------+-------+------+---------------+------+---------+------+------+-------+

    explain 有两个变种:

    1)explain extended:会在 explain  的基础上额外提供一些查询优化的信息。紧随其后通过 show warnings 命令可以 得到优化后的查询语句,从而看出优化器优化了什么。额外还有 filtered 列,是一个半分比的值,rows * filtered/100 可以估算出将要和 explain 中前一个表进行连接的行数(前一个表指 explain 中的id值比当前表id值小的表)。

    mysql> explain extended select * from t_user where id = 1;

    +----+-------------+-------+-------+---------------+---------+---------+-------+------+----------+-------+

    | id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |

    +----+-------------+-------+-------+---------------+---------+---------+-------+------+----------+-------+

    |  1 | SIMPLE      | t_user | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL  |

    +----+-------------+-------+-------+---------------+---------+---------+-------+------+----------+-------+

    2)explain partitions:相比 explain 多了个 partitions 字段,如果查询是基于分区表的话,会显示查询将访问的分区。

    2.explain详解

    1. id列

    序列号,SQL的顺序

    2. select_type列

    查询类型

    1)simple:简单查询。查询不包含子查询和union

    mysql> explain select * from t_user where id = 2;

    +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+

    | id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra |

    +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+

    |  1 | SIMPLE      | t_user | const | PRIMARY       | PRIMARY | 4       | const |    1 | NULL  |

    +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+

    2)primary:复杂查询中最外层的 select

    3)subquery:包含在 select 中的子查询(不在 from 子句中)

    4)derived:包含在 from 子句中的子查询。MySQL会将结果存放在一个临时表中,也称为派生表(derived的英文含义)

    mysql> explain select (select 1 from t1 where id = 1) from (select * from t2 where id = 1) d;

    +----+-------------+------------+--------+---------------+---------+---------+-------+------+-------------+

    | id | select_type | table      | type   | possible_keys | key     | key_len | ref   | rows | Extra       |

    +----+-------------+------------+--------+---------------+---------+---------+-------+------+-------------+

    |  1 | PRIMARY     | <derived3> | system | NULL          | NULL    | NULL    | NULL  |    1 | NULL        |

    |  3 | DERIVED     | t2       | const  | PRIMARY       | PRIMARY | 4       | const |    1 | NULL        |

    |  2 | SUBQUERY    | t1      | const  | PRIMARY       | PRIMARY | 4       | const |    1 | Using index |

    +----+-------------+------------+--------+---------------+---------+---------+-------+------+-------------+

    5)union:在 union 中的第二个和随后的 select

    6)union result:从 union 临时表检索结果的 select

    mysql> explain select 1 union all select 1;

    +----+--------------+------------+------+---------------+------+---------+------+------+-----------------+

    | id | select_type  | table      | type | possible_keys | key  | key_len | ref  | rows | Extra           |

    +----+--------------+------------+------+---------------+------+---------+------+------+-----------------+

    |  1 | PRIMARY      | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL | No tables used  |

    |  2 | UNION        | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL | No tables used  |

    | NULL | UNION RESULT | <union1,2> | ALL  | NULL          | NULL | NULL    | NULL | NULL | Using temporary |

    +----+--------------+------------+------+---------------+------+---------+------+------+-----------------+

    3. table列

    这一列表示 explain 的一行正在访问哪个表。

    当 from 子句中有子查询时,table列是 <derivenN> 格式,表示当前查询依赖 id=N 的查询,于是先执行 id=N 的查询。当有 union 时,UNION RESULT 的 table 列的值为 <union1,2>,1和2表示参与 union 的 select 行id。

    4. type列 (重点关注)

    这一列表示关联类型或访问类型,即MySQL决定如何查找表中的行。

    依次从最优到最差分别为:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

    const、system:

    表最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读取一次!

    eq_ref:primary key 或 unique key 索引的所有部分被连接使用 ,最多只会返回一条符合条件的记录。。

    ref:相比 eq_ref,不使用唯一索引,而是使用普通索引或者唯一性索引的部分前缀,索引要和某个值相比较,可能会找到多个符合条件的行;

    ref_or_null:类似ref,但是可以搜索值为NULL的行。

    index_merge:表示使用了索引合并的优化方法。 比如:条件中使用or 比较两个查询条件都存在索引。

    range:范围扫描通常出现在 in(), between ,> ,<, >= 等操作中。使用一个索引来检索给定范围的行。

    index:和ALL一样,不同就是mysql只需扫描索引树,这通常比ALL快一些。

    ALL:即全表扫描,意味着mysql需要从头到尾去查找所需要的行。通常情况下这需要增加索引来进行优化了

    5. possible_keys列

     表明可能使用哪些索引来查找。

    explain 时可能出现 possible_keys 有列,而 key 显示 NULL 的情况,这种情况是因为表中数据不多,mysql认为索引对此查询帮助不大,选择了全表查询。

    如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查 where 子句看是否可以创造一个适当的索引来提高查询性能,然后用 explain 查看效果。

    6. key列 (重点关注)

    这一列显示mysql实际采用哪个索引来优化对该表的访问。

    如果没有使用索引,则该列是 NULL。如果想强制mysql使用或忽视possible_keys列中的索引,在查询中使用 force index、ignore index。

    7. key_len列(重点关注)

    这一列显示了mysql在索引里使用的字节数,通过这个值可以算出具体使用了索引中的哪些列。使用的索引的长度。在不损失精确性的情况下,长度越短越好。

    比如,a_b的联合索引 idx_a_b_id 由 a_id 和 b_id 两个int列组成,并且每个int是4字节。通过结果中的key_len=4可推断出查询使用了第一个列:a_id列来执行索引查找。

    char(n):n字节长度

    varchar(n):2字节存储字符串长度,如果是utf-8,则长度 3n + 2

    tinyint:1字节

    smallint:2字节

    int:4字节

    bigint:8字节  

    date:3字节

    timestamp:4字节

    datetime:8字节

    如果字段允许为 NULL,需要1字节记录是否为 NULL

    索引最大长度是768字节,当字符串过长时,mysql会做一个类似左前缀索引的处理,将前半部分的字符提取出来做索引。

    8. ref

    ref列显示在key列记录的索引中,表查找值所用到的列或常量,常见的有:const(常量),func,NULL,字段名

    9. rows (重点关注)

    rows列显示MySQL估计执行查询时必须检查的行数。

    10. Extra展示额外信息

    distinct: 一旦mysql找到了与行相联合匹配的行,就不再搜索了

    Using index:这发生在对表的请求列都是同一索引的部分的时候,返回的列数据只使用了索引中的信息,而没有再去访问表中的行记录。是性能高的表现。

    Using where:mysql服务器将在存储引擎检索行后再进行过滤。就是先读取整行数据,再按 where 条件进行检查,符合就留下,不符合就丢弃。

    Using temporary:mysql需要创建一张临时表来处理查询。出现这种情况一般是要进行优化的。(重点关注)

  • 相关阅读:
    C/C++多文件之间的变量定义
    PKU POJ 2186 Popular Cows 强连通分量
    重载函数
    ZOJ 2763 Prison Break
    201357 训练赛总结
    hdu 4467 Graph 构造
    201356 训练赛总结
    201353 NEERC 2012, Eastern subregional contest
    2013512 CF 183 总结
    一道动态规划
  • 原文地址:https://www.cnblogs.com/brant/p/12817973.html
Copyright © 2011-2022 走看看