MySQL执行计划

Posted wanbin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL执行计划相关的知识,希望对你有一定的参考价值。

mysql执行计划

  • 使用EXPLAIN优化查询

  • EXPLAIN输出格式

  • 扩展EXPLAIN输出格式

  • 获取命名连接的执行计划信息

  • 估计查询性能

EXPLAIN 语法

{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
}

 

1. 使用EXPLAIN优化查询

EXPLAIN语句提供有关MySQL如何执行语句的信息:

  • EXPLAIN适用于SELECT,DELETE,INSERT,REPLACE和UPDATE语句。

  • 当EXPLAIN与可解释的语句一起使用时,MySQL会显示优化器中有关语句执行计划的信息。也就是说,MySQL解释了它将如何处理语句,包括有关表如何连接以及以何种顺序连接的信息。

  • 当EXPLAIN与FOR CONNECTION connection_id将显示connection_id执行的语句的执行计划。

  • 对于SELECT语句,EXPLAIN会生成可以使用SHOW WARNINGS显示的其他执行计划信息。

  • EXPLAIN对于检查涉及分区表的查询很有用。

  • FORMAT选项可用于选择输出格式。 TRADITIONAL以表格格式显示输出。如果没有显示定义FORMAT选项,则默认值为TRADITIONAL。 JSON格式以JSON格式显示信息。

在EXPLAIN的帮助下,可以看到应该向表添加索引的位置,以便通过使用索引查找行来更快地执行语句。还可以使用EXPLAIN来检查优化程序是否以最佳顺序连接表。要提示优化器使用与SELECT语句中命名表的顺序相对应的连接顺序,请使用SELECT STRAIGHT_JOIN而不是SELECT来开始语句。 (请参见“SELECT语法”。)但是,STRAIGHT_JOIN可能会阻止使用索引,因为它会禁用半连接转换。请参见“使用半连接转换优化子查询,派生表和视图引用”。

优化器跟踪有时可以提供与EXPLAIN的信息互补的信息。但是,优化程序跟踪格式和内容可能会在不同版本之间发生变化。有关详细信息,请参阅MySQL内部:跟踪优化程序

如果在您认为应该使用索引时遇到问题,请运行ANALYZE TABLE以更新可能影响优化程序所做选择的表统计信息,例如key的基数。请参见“ANALYZE TABLE语法”

注意
EXPLAIN还可用于获取有关表中列的信息。 EXPLAIN tbl_nameDESCRIBE tbl_nameSHOW COLUMNS FROM tbl_name同义。

2. EXPLAIN输出格式

EXPLAIN语句提供有关MySQL如何执行语句的信息。 EXPLAIN适用于SELECTDELETEINSERTREPLACE和UPDATE语句。

EXPLAIN为SELECT语句中使用的每个表返回一行信息。 它按照MySQL在处理语句时读取它们的顺序列出输出中的表。 MySQL使用嵌套循环连接方法解析所有连接。 这意味着MySQL从第一个表中读取一行,然后在第二个表,第三个表中找到匹配的行,依此类推。 处理完所有表后,MySQL会通过表列表输出所选列和回溯,直到找到有更多匹配行的表。 从该表中读取下一行,并继续下一个表。

EXPLAIN输出包括分区信息。 此外,对于SELECT语句,EXPLAIN生成扩展信息,可以使用EXPLAIN后的SHOW WARNINGS显示.

【注意】
在较旧的MySQL版本中,使用EXPLAIN PARTITIONSEXPLAIN EXTENDED生成分区和扩展信息。 这些语法仍然可以向后兼容,但默认情况下现在启用分区和扩展输出,因此PARTITIONS和EXTENDED关键字是多余的并且已弃用。 它们的使用会导致警告,并且在将来的MySQL版本中它们将从EXPLAIN语法中删除。

您不能在同一个EXPLAIN语句中一起使用已弃用的PARTITIONS和EXTENDED关键字。 此外,这些关键字都不能与FORMAT选项一起使用。

2.1 EXPLAIN输出列

mysql> explain select * from employees.t1 where t1.emp_no in (select emp_no from employees.salaries);
+----+--------------+-------------+------------+--------+----------------+------------+---------+---------------------+---------+----------+-------------+
| id | select_type  | table       | partitions | type   | possible_keys  | key        | key_len | ref                 | rows    | filtered | Extra       |
+----+--------------+-------------+------------+--------+----------------+------------+---------+---------------------+---------+----------+-------------+
|  1 | SIMPLE       | t1          | NULL       | ALL    | NULL           | NULL       | NULL    | NULL                | 2837194 |   100.00 | Using where |
|  1 | SIMPLE       | <subquery2> | NULL       | eq_ref | <auto_key>     | <auto_key> | 4       | employees.t1.emp_no |       1 |   100.00 | NULL        |
|  2 | MATERIALIZED | salaries    | NULL       | index  | PRIMARY,emp_no | emp_no     | 4       | NULL                | 2838426 |   100.00 | Using index |
+----+--------------+-------------+------------+--------+----------------+------------+---------+---------------------+---------+----------+-------------+
3 rows in set, 1 warning (0.00 sec)

 

EXPLAIN的每个输出行都提供有关一个表的信息。如下表:

ColumnJSON NameMeaning
id select_id 查询序列号
select_type None 查询类型
table table_name 输出行所引用的表
partitions partitions 匹配的分区
type access_type 连接使用的类型
possible_keys possible_keys 指出 MySQL 能在该表中使用哪些索引有助于查询。如果为空,说明没有可用的索引
key key 实际选择的索引
key_len key_length 使用的索引的长度。在不损失精确性的情况下,长度越短越好
ref ref 显示索引的哪一列被使用了
rows rows MYSQL 认为必须检查的用来返回请求数据的行数
filtered filtered 按表条件过滤行的百分比
Extra None 附加信息

 

  • id(JSON Name: select_id)
    • MySQL Query Optimizer 选定的执行计划中查询的序列号。表示查询中执行 select 子句或操作表的顺序, id 值越大优先级越高,越先被执行。 id 相同,执行顺序由上至下。
  • select_type (JSON name: none)
    • SELECT的类型,可以是下表中列出的任何类型。
select_type ValueJSON NameMeaning
SIMPLE None 简单的SELECT(不使用UNION或子查询)
PRIMARY None 最外层的SELECT
UNION None UNION 中的第二个或随后的 select 查询, 不依赖于外部查询的结果集
DEPENDENT UNION dependent (true) UNION中的第二个或随后的SELECT语句,依赖于外部查询
UNION RESULT union_result UNION 查询的结果集
SUBQUERY None 子查询中的第一个SELECT查询,不依赖于外部查询的结果集
DEPENDENT SUBQUERY dependent (true) 子查询中的第一个SELECT,依赖于外部查询的结果集
DERIVED None 用于 from 子句里有子查询的情况。 MySQL会递归执行这些子查询,把结果放在临时表里
MATERIALIZED materialized_from_subquery 物化子查询
UNCACHEABLE SUBQUERY cacheable (false) 结果集不能被缓存的子查询,必须重新为外层查询的每一行进行评估
UNCACHEABLE UNION cacheable (false) UNION 中的第二个或随后的 select 查询,属于不可缓存的子查询
    • DEPENDENT通常表示使用相关子查询。
    • DEPENDENT SUBQUERY评估与UNCACHEABLE SUBQUERY评估不同。 对于DEPENDENT SUBQUERY,子查询仅针对来自其外部上下文的变量的每组不同值重新评估一次。 对于UNCACHEABLE SUBQUERY,将为外部上下文的每一行重新评估子查询。
    • 子查询的可缓存性与查询缓存中查询结果的缓存不同(详见“查询缓存如何操作”)。 查询执行期间发生子查询缓存,而查询缓存仅在查询执行完成后用于存储结果。使用EXPLAIN指定FORMAT = JSON时,输出没有直接等同于  select_type的单个属性; query_block属性对应于给定的SELECT。 可以使用与刚显示的大多数SELECT子查询类型等效的属性(示例为MATERIALIZED的materialized_from_subquery),并在适当时显示。 SIMPLE或PRIMARY没有JSON等价物。
    • 非SELECT语句的select_type值显示受影响表的语句类型。 例如,对于DELETE语句,select_type是DELETE。
  • table (JSON name: table_name)
    输出行引用的表的名称。这也可以是以下值之一:
    • <unionM,N>:该行指的是id值为M和N的行的并集。
    • <derivedN>:该行引用id值为N的行的派生表结果。例如,派生表可能来自FROM子句中的子查询。
    • <subqueryN>:该行引用id值为N的行的具体化子查询的结果
  • partitions (JSON name: partitions)
    • 记录将与查询匹配的分区。对于非分区表,该值为NULL。
  • type (JSON name: access_type)
    • 连接类型。用于描述不同的连接类型
  • possible_keys (JSON name: possible_keys)
    • possible_keys指出 MySQL 能在该表中使用哪些索引有助查询。如果为空,说明没有可用的索引
  • key (JSON name: key)
    • key列表示MySQL实际决定使用的key(索引)。如果MySQL决定使用其中一个possible_keys索引来查找行,那么该索引将被列为key value。
    • key可能会命名possible_keys值中不存在的索引。如果所有possible_keys索引都不适合查找行,则会发生这种情况,但查询选择的所有列都是其他索引的列。也就是说,命名索引覆盖了所选列,因此虽然它不用于确定要检索的行,但索引扫描比数据行扫描更有效。
    • 对于InnoDB,即使查询还选择主键,辅助索引也可能覆盖所选列,因为InnoDB将主键值与每个辅助索引一起存储。如果key为NULL,则MySQL找不到用于更有效地执行查询的索引。
    • 要强制MySQL使用或忽略possible_keys列中列出的索引,请在查询中使用FORCE INDEXUSE INDEXIGNORE INDEX。请参考“索引hint”
    • 对于MyISAM表,运行ANALYZE TABLE可帮助优化器选择更好的索引。对于MyISAM表,myisamchk --analyze也是如此。
  • key_len (JSON name: key_length)



以上是关于MySQL执行计划的主要内容,如果未能解决你的问题,请参考以下文章

MySQL执行计划

如何查看sqlserver执行计划来判断SQL语句效率

如何查看mysql定时任务计划

MySQL系列- MySQL执行计划

Mysql学会查看sql的执行计划

mysql中如何查看优化器优化后的执行计划