关于mysql:MySQL-使用explain-优化查询性能

Explain 介绍

为了优化MySQL的SQL语句的执行性能,MySQL提供了explain关键字用于查看SQL的执行打算。
格局如下:

{EXPLAIN | DESCRIBE | DESC}
    tbl_name [col_name | wild]

{EXPLAIN | DESCRIBE | DESC}
    [explain_type]
    {explainable_stmt | FOR CONNECTION connection_id}

explain_type: {
    EXTENDED
  | PARTITIONS
  | FORMAT = format_name
}

format_name: {
    TRADITIONAL
  | JSON
}

explainable_stmt: {
    SELECT statement
  | DELETE statement
  | INSERT statement
  | REPLACE statement
  | UPDATE statement
}

DESCRIBE和EXPLAIN语句是同义词。实际上,DESCRIBE关键字更罕用于获取无关表构造的信息,而EXPLAIN用于获取查问执行打算(即,解释MySQL将如何执行查问)。

从下面的EXPLAIN的用法能够看出:

  • EXPLAIN 能够与 SELECT, DELETE, INSERT, REPLACE 和 UPDATE 一起应用,用于查问相应SQL的执行打算。
  • 当EXPLAIN与可解释语句(explainable statement)一起应用时,MySQL显示来自优化器的对于语句执行打算的信息。也就是说,MySQL解释了它将如何解决该语句,包含无关如何联接表以及以何种程序联接表的信息。
  • 当EXPLAIN与FOR CONNECTION connect_id 而不是可解释语句一起应用时,它将显示在命名连贯中执行的语句的执行打算。
  • 对于SELECT语句,EXPLAIN能够应用SHOW WARNINGS 语句显示的其余额定的执行打算信息。
  • EXPLAIN对于查看波及分区表的查问很有用。
  • FORMAT选项可用于抉择输入格局。TRADITIONAL以表格格局显示输入,默认为TRADITIONAL,JSON格局以JSON格局显示信息。

在EXPLAIN的帮忙下,能够看到应该在哪里向表增加索引,以便通过应用索引查找使语句执行得更快,还能够应用EXPLAIN查看优化器是否以最佳程序连贯表。

当EXPLAIN与SELECT语句一起应用时,EXPLAIN的后果以表格的格局显示输入,每个行示意一张表。MYSQL应用循环内嵌的办法解析所有的表的连贯,也就意味着MYSQL会先读取第一张表的第一行,而后在第二张表中查找匹配的行,而后是第三张表等。当所有的表格都解决实现之后,MySQL输入所选列并回溯所有表,直到找到一个表,其中有更多匹配行。从该表中读取下一行,并持续解决下一个表。

Explain 的输入

EXPLAIN中的每个输入行提供对于一个表的信息。
EXPLAIN的输入如下(第二列为FORMAT=JSON时的输入):

Column JSON Name Meaning
id select_id The SELECT identifier
select_type None The SELECT type
table table_name The table for the output row
partitions partitions The matching partitions
type access_type The join type
possible_keys possible_keys The possible indexes to choose
key key The index actually chosen
key_len key_length The length of the chosen key
ref ref The columns compared to the index
rows rows Estimate of rows to be examined
filtered filtered Percentage of rows filtered by table condition
Extra None Additional information

上面对下面的每一列逐个阐明:
id : 这是查问中SELECT的序列号。如果该行指的是其余行的UNION后果,则该值能够为NULL。在这种状况下,table 列显示一个相似<unionM,N>的值,以批示该行援用id值为M和N的行的并集。

explain select * from small_note.small_note_detail where id = 5 union select * from small_note.small_note_detail where id = 6;

后果如下:

select_type: select_type的取值如下:

select_type Value Meaning
SIMPLE 简略查问,没有应用UNION和子查问
PRIMARY 最外层的SELECT语句
UNION UNION中第二个或者更后的SELECT语句
DEPENDENT UNION UNION中的第二个或当前的SELECT语句,依赖于内部查问
UNION RESULT UNION的后果,因为它不须要参加查问,所以id字段为NULL
SUBQUERY 除了from字句中蕴含的子查问外,其余中央呈现的子查问都可能是SUBQUERY类型
DEPENDENT SUBQUERY 子查问中的第一个SELECT语句, 依赖于内部查问, 对于上下文中变量的每一组不同值,子查问只从新计算一次
DERIVED FROM语句中呈现的子查问,也叫做派生表, 当FROM语句中蕴含多个SELECT语句时,第一个SELECT语句的select_type也可能为DERIVED
MATERIALIZED 物化的字查问
UNCACHEABLE SUBQUERY 子查问的后果不能缓存下来,对于内部查问的每一行都须要从新计算
UNCACHEABLE UNION UNION中的第二个或当前的SELECT语句属于UNCACHEABLE SUBQUERY

DEPENDENT SUBQUERY与UNCACHEABLE SUBQUERY不同。对于DEPENDENT SUBQUERY,对于内部上下文中变量的每一组不同值,子查问只从新计算一次。对于UNCACHEABLE SUBQUERY,将为内部上下文的每一行从新计算子查问。

非SELECT语句的select_type为语句的type, 比方对于DELETE语句而言,其select type 就是DELETE。

table: 表的名称。除了能够是表的名称,这也能够是以下值之一。

<unionM,N>:该行示意id值为M和N的行的并集。

<derived N>:该行援用id值为N的行的派生表后果。例如,派生表可能来自from子句中的子查问。

<subquery N>:该行是指id值为N的行的物化子查问的后果。

partitions : 查问匹配的分区,对于非分区表,该值为NULL。

type:关联类型,决定通过什么形式找到每一行数据。以下依照速度由快到慢。
system>const>eq_ref>ref>fulltext>ref_or_null>index_merge>unique_subquery>index_subquery>range>index>ALL。

  • system,表中只有一行记录,相当于零碎表;
  • const,该表最多有一个匹配行,在查问开始时读取。因为只有一行,所以优化器的其余部分能够将此行中列的值视为常量。常量表十分快,因为它们只读取一次。将主键或惟一索引的所有局部与常量值进行比拟时,type将是const。
  • eq_ref,读取本表中和关联表表中的每行组合成的一行,即只返回一条数据。除了system和const类型之外,这是最好的联接类型。当联接应用索引的所有局部,并且索引是主键或惟一的非空索引时,type为eq_ref。
  • ref,将从此表中读取具备匹配索引值的所有行。如果联接仅应用键的最左侧前缀,或者键不是主键或惟一索引(换句话说,如果联接无奈基于键值抉择单行),则应用ref。如果应用的键只匹配几行,则这是一种良好的联接类型。ref可用于应用=或<=>运算符进行比拟的索引列。
  • fulltext, 应用FULLTEXT索引
  • ref_or_null, 和ref相似,然而还要进行一次查问找到NULL的数据。
  • index_merge, 对于单表查问(无奈跨表合并)用到了多个索引的状况,每个索引都可能返回一个后果,Mysql会对后果进行取并集、交加,这就是索引合并了。
  • unique_subquery, 对于in的子查问中应用了惟一索引,有的时候应用unique_subquery而不是eq_ref
  • index_subquery, 和unique_subquery相似,只是针对的是非惟一索引。
  • range,只检索给定范畴的行,应用一个索引来抉择行,个别用于between、<、>;
  • index,只遍历索引树;
  • all,全表扫描;

possible_keys: 示意MySQL能够从中抉择查找此表中的行的索引。请留神,此列齐全独立于EXPLAIN输入中显示的表格程序。这意味着possible_keys中的一些键在理论生成的表程序中可能不可用。

key: 示意MySQL理论决定应用的键(索引)。如果MySQL决定应用possible_keys中的某个索引来查找行,则该索引将作为键值列出。key也可能是possible_keys中不存在的索引,如果所有possible_keys都不适宜查找行,但查问抉择的所有列都是其余索引的列,则可能产生这种状况。也就是说,命名索引笼罩选定的列,因而只管它不用于确定要检索的行,但索引扫描比数据行扫描更无效。

key_len: key_len列示意MySQL决定应用的key的长度(字节),char为4个字节,容许为NULL须要额定一个字节,不定长还须要额定2个字节存储长度。如果key列示意NULL,则key_len列也示意NULL。

ref: 显示该表的索引字段关联了哪张表的哪个字段;

rows: 示意MySQL认为执行查问必须查看的行数。

filtered:返回后果的行数占读取行数的百分比,值越大越好;

extra:蕴含不适宜在其余列中显示但非常重要的额定信息。常见的值如下:

  • using filesort,MySQL会对数据应用一个内部索引排序,而不是依照表内索引程序进行读取,若呈现改值,则应优化SQL语句;
  • using temporary,应用长期表缓存两头后果,比方,MySQL在对查问后果排序时应用长期表,常见于order by和group by,若呈现该值,则应优化SQL;
  • using index,仅应用索引树中的信息从表中检索列信息,而无需进行额定的查找以读取理论行。 当查问仅应用属于单个索引的列时,能够应用此策略。示意select操作应用了笼罩索引,防止了拜访表的数据行;
  • Using index condition, 应用索引下推,索引下推简略来说就是加上了条件筛选,须要回表,然而缩小了回表的操作。
  • using where,where子句用于限度哪一行;
  • using join buffer,应用连贯缓存;
  • distinct,发现第一个匹配后,进行为以后的行组合搜寻更多的行;

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理