Explain查询MySQL执行计划
用 explain 来优化查询
explain 语句能够提供 MySQL 执行语句的信息,即语句的执行计划
。
explain 支持的语句有:
- select
- delete
- insert
- replace
- update
explain 对 select 语句的输出格式:(官网: https://dev.mysql.com/doc/refman/5.7/en/explain-output.html )
- id -- 查询的标识符(the select identifier)
- select_type -- 查询的类型(the select type)
- table -- 表名(the table for output row)
- partitions -- 匹配的分区(the matching partitions)
- type -- 连接类型(the join type)
- possible_keys -- 可能选择的索引(the possible indexes to choose)
- key -- 实际选择的索引(the index actually chosen)
- key_len -- 实际选择的索引的长度(the length of the chosen key)
- ref -- 与索引比较的列(the columns compared to the index)
- rows -- 要扫描的估计的行数(estimate of rows to be examined)
- filtered -- 被表条件过滤的表的估计百分比(percentage of rows filtered by table condition)
- Extra -- 额外的信息(additional information)
详解 explain 输出的信息
id: 查询的标识符,即查询语句中每个 select 的顺序号。值可以为null,当前行引用的是其它行的并集(union)结果。
select_type: select的类型
- simple
- 简单的 select,即没有用 union 或子查询
- simple select,not using union or subqueries
- primary
- 外层 select
- outermost select
- union
- 在一个 union 的第二或后面的 select
- second or later select statement in a union
- dependent union
- 依靠外层查询的第二或后面的 select 在一个 union
- second or later select statement in a union,dependent on outer query
- union result
- 一个 union 的结果
- result of a union
- subquery
- 子查询的第一个 select
- first select in subquery
- dependent subquery
- 依靠外层查询的子查询的第一个 select
- first select in subquery,dependent on outer query
- derived
- 派生表
- derived table
- materialized
- 物化子查询
- materialized subquery
- uncacheable subquery
- 一个子查询,即结果不能被缓存且要外层查询要重新查询
- a subquery for which the result cannot be cached and must be re-evaluated for each row of the outer query
- uncacheable union
- 在一个 union 的第二或后面的 select,属于一个不能缓存的子查询,跟 uncacheable query 一样
- the second or later select in a union that belongs to an uncacheable subquery(see uncacheable subquery)
table: 表名,即 explain 输出的行所引用的表名,也可以是下面的值:
<unionM,N>
: 即 id 值为 M 和 N 的 union<derivedN>
: 即 id 值为 N 的派生表<subqueryN>
: 即 id 值为 N 的物化子查询
partitions: 匹配的分区,即被查询匹配上的记录所在的分区,表没有分区的话就是 null
type: 连接类型(官网: https://dev.mysql.com/doc/refman/5.7/en/explain-output.html#explain-join-types )
- system: 只有一条记录的表,这是一种特殊情况
- const: 在查询开始时读取,表中最多有一个匹配的行记录,即只读一次,所以非常快
- 用了
主键索引
或唯一索引
的列为查询条件,而它的值是常量时,会用到 const- 如果其它的查询条件匹配失败,type 则为null,Extra 列中会有: Impossible WHERE noticed after reading const tables
- 用了
- eq_ref:
- 在联表查询中,对上一个表每一行的组合,从当前表中读取一行,而关联条件的字段用的是
主键索引
或唯一索引
的列,它的值可以为常量,也可以为关联表的字段。
- 在联表查询中,对上一个表每一行的组合,从当前表中读取一行,而关联条件的字段用的是
- ref:
- 查询中,用了
主键索引
或唯一索引
的列的前缀(就是匹配到的一止一行记录),或者用的是主键索引
及唯一索引
之外的索引。
- 查询中,用了
- fulltext
- 联接用的是
全文索引
执行的
- 联接用的是
- ref or null
- 与 ref 类似,但是mysql会额外扫描包含空值的行。比如:
select * from ref_table where key_column=exepr or key_column is null;
- 与 ref 类似,但是mysql会额外扫描包含空值的行。比如:
- index merge
- 执行计划用了
索引合并
优化- key 的那一列会展示用到的索引;
- key_len 的那一列会展示的长度是最长长度的索引的。
--> 合并的索引比较多,会影响性能,应该考虑加一个联合索引
- 执行计划用了
- unique subquery
- 被用 in () 括起来的子查询,子查询是 eq_ref 的 type,其 type 会被替换成 unique subquery
- index subquery
- 与 unique subquery 类型,是被用 in () 括起来的子查询,但不同的是子查询中用的索引不是
唯一索引
- 与 unique subquery 类型,是被用 in () 括起来的子查询,但不同的是子查询中用的索引不是
- range
- 仅查询给定范围的行记录,且使用了索引;
- 给定范围的方式包括用: =, <>, >, >=, <, <=, is null, <=>, between, like, in()等。
- key 的那一列会展示用到的索引;
- key_len 的那一列会展示的长度是最长长度的索引的。
- 仅查询给定范围的行记录,且使用了索引;
- index
- 跟全表扫描类型,不过是在索引树上扫描,比全表扫描要快。
- 如果索引是查询的
覆盖索引
,并且可用于满足表中所需的所有数据,则仅扫描索引树。- Extra 列会展示: Using index;
- 使用从索引中读取的数据执行全表扫描,以按索引顺序查找数据行。
- 如果索引是查询的
- 跟全表扫描类型,不过是在索引树上扫描,比全表扫描要快。
- all
- 即全表扫描查询。
小结:
1、就查效率来说:system > const > eq_ref > ref > range > index > all
2、index merge 是个坑,因为加太多索引的情况,全并索引的结果会开销比较大,还不如全表扫描。