MySQL EXPLAIN 命令: 查看查询执行计划

MySQL 的 EXPLAIN 命令能够查看SELECT语句的执行的计划,是 MySQL 查询优化的必备工具。sql

经过执行计划能够了解查询方式、索引使用状况、须要扫描的数据量以及是否须要临时表或排序操做等信息。数据库

咱们须要分析执行计划对查询进行有的放矢的优化。缓存

须要注意:服务器

  • EXPLAIN不考虑触发器、存储过程或用户自定义函数对查询的影响
  • EXPLAIN不考虑缓存
  • EXPLAIN只能分析执行计划,不能显示存储引擎在执行查询过程当中进行的操做
  • 部分统计信息是估算的,并不是精确值

本文基于 MySQL 5.6 版本。函数

EXPLAIN SELECT * FROM `user`
  JOIN `post` ON `user`.id = `post`.uid
WHERE user.`created_at` < '2018-10-01 00:00:00' AND `post`.status = 1;

结果:工具

id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE user range PRIMARY,idx_created_at idx_created_at 7 null 19440 Using index condition; Using where; Using temporary; Using filesort
1 SIMPLE post ref idx_uid,idx_status idx_uid 8 user.id 1 Using where

EXPLAIN 的行数为查询涉及的表数, 结果各列的含义为:post

  • id: 查询的惟一标识
  • select_type: 查询的类型
  • table: 查询的表, 多是数据库中的表/视图,也多是 FROM 中的子查询
  • type: 搜索数据的方法
  • possible_keys: 可能使用的索引
  • key: 最终决定要使用的key
  • key_len: 查询索引使用的字节数。一般越少越好
  • ref: 查询的列或常量
  • rows: 须要扫描的行数,估计值。一般越少越好
  • extra: 额外的信息

select type

select_type 可能的值有:优化

  • SIMPLE: 简单查询,不包含子查询和union
  • PRIMRARY: 包含子查询时的最外层查询; 使用union时的第一个查询
  • UNION: 包含union的查询中非第一个查询
  • DEPENDENT UNION: 与 UNION 相同,但依赖外层查询的结果
  • SUBQUERY: 子查询
  • DEPENDENT SUBQUERY: 依赖外层查询的子查询
  • DERIVED: 用于 FROM 中的子查询

下面给出几个示例:ui

EXPLAIN SELECT * FROM post WHERE uid = (
  SELECT id FROM user WHERE name = "finley"
);
id select_type table
1 PRIMARY post
2 SUBQUERY user

DEPENDENT SUBQUERY:code

EXPLAIN SELECT * FROM post WHERE uid = (
  SELECT id FROM user WHERE name = "finley" AND post.uid=user.id
);
id select_type table
1 PRIMARY post
2 DEPENDENT SUBQUERY user

type

type 字段描述了查询的方式,从好到坏为:

  1. null: 不须要访问索引和表便可完成, 示例: SELECT 1;
  2. const: 表中仅有一行匹配,在分解查询计划时直接将其读出做为常量使用。system 是 const 类型的特例。
    示例:SELECT id FROM user WHERE name = "hdt3213";

    id select_type table type possible_keys key key_len ref rows Extra
    1 SIMPLE user const uni_name uni_name 258 const 1 Using index

UNIQUE KEY uni_name (name) ON user

  1. eq_ref: 使用 PRIMARY KEY 或 UNIQUE KEY 进行关联查询。
    示例: SELECT * FROM post JOIN user ON post.uid = user.id WHERE user.gender = 'M';

    id select_type table type possible_keys key key_len ref rows Extra
    1 SIMPLE post ALL idx_uid 0 0 0 57796 null
    1 SIMPLE user eq_ref PRIMARY PRIMARY 8 post.uid 1 Using where
  2. ref: 使用容许重复的索引进行查询
    示例: SELECT * FROM user WHERE phone='12345678901';

    id select_type table type possible_keys key key_len ref rows Extra
    1 SIMPLE user ref idx_phone idx_phone 259 const 1 Using index condition
  3. range: 使用索引进行范围查询:
    示例: SELECT * FROM user WHERE age>18;

    id select_type table type possible_keys key key_len ref rows Extra
    1 SIMPLE user ref idx_age idx_age 259 const 1 null
  4. index: 在索引上进行顺序扫描。常见于在多列索引中未使用最左列进行查询。
    示例: SELECT * FROM user WHERE last_name='smith'

    id select_type table type possible_keys key key_len ref rows Extra
    1 SIMPLE user ref idx_full_name idx_full_name 259 const 1 Using where
  5. all: 扫描全表,最坏的状况

extra

extra 列显示了查询过程当中须要执行的其它操做,有些状况应尽力避免。

  • using filesort: 查询时执行了排序操做而没法使用索引排序。虽然名称为'file'但操做多是在内存中执行的,取决是否有足够的内存进行排序。
    应尽可能避免这种filesort出现。
  • using temporary: 使用临时表存储中间结果,常见于ORDER BY和GROUP BY语句中。临时表可能在内存中也可能在硬盘中,应尽可能避免这种操做出现。
  • using index: 索引中包含查询的全部列(覆盖索引)不须要查询数据表。能够加快查询速度。
  • using index condition: 索引条件推送(MySQL 5.6 新特性),服务器层将不能直接使用索引的查询条件推送给存储引擎,从而避免在服务器层进行过滤。
  • using where: 服务器层对存储引擎返回的数据进行了过滤
  • distinct: 优化distinct操做,查询到匹配的数据后中止继续搜索
相关文章
相关标签/搜索