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_name
与DESCRIBE tbl_name
和SHOW COLUMNS FROM tbl_name
同义。
2. EXPLAIN输出格式
EXPLAIN语句提供有关MySQL如何执行语句的信息。 EXPLAIN适用于SELECT
,DELETE
,INSERT
,REPLAC
E和UPDATE
语句。
EXPLAIN为SELECT语句中使用的每个表返回一行信息。 它按照MySQL在处理语句时读取它们的顺序列出输出中的表。 MySQL使用嵌套循环连接方法解析所有连接。 这意味着MySQL从第一个表中读取一行,然后在第二个表,第三个表中找到匹配的行,依此类推。 处理完所有表后,MySQL会通过表列表输出所选列和回溯,直到找到有更多匹配行的表。 从该表中读取下一行,并继续下一个表。
EXPLAIN输出包括分区信息。 此外,对于SELECT语句,EXPLAIN生成扩展信息,可以使用EXPLAIN后的SHOW WARNINGS
显示.
【注意】
在较旧的MySQL版本中,使用EXPLAIN PARTITIONS
和EXPLAIN EXTENDED
生成分区和扩展信息。 这些语法仍然可以向后兼容,但默认情况下现在启用分区和扩展输出,因此PARTITIONS和EXTENDED关键字是多余的并且已弃用。 它们的使用会导致警告,并且在将来的MySQL版本中它们将从EXPLAIN语法中删除。您不能在同一个EXPLAIN语句中一起使用已弃用的PARTITIONS和EXTENDED关键字。 此外,这些关键字都不能与FORMAT选项一起使用。
-
EXPLAIN join 类型
-
EXPLAIN Extra 信息
-
EXPLAIN输出解释
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的每个输出行都提供有关一个表的信息。如下表:
Column | JSON Name | Meaning |
---|---|---|
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 Value | JSON Name | Meaning |
---|---|---|
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 INDEX
,USE INDEX
或IGNORE INDEX
。请参考“索引hint”。 - 对于MyISAM表,运行ANALYZE TABLE可帮助优化器选择更好的索引。对于MyISAM表,myisamchk --analyze也是如此。
- key_len (JSON name: key_length)
以上是关于MySQL执行计划的主要内容,如果未能解决你的问题,请参考以下文章