本文是关于在学习《高性能 Mysql》附录 D 中关于 Explain 如何获取执行计划信息相关总结。MySQL 提供了一个 EXPLAIN 命令,它可以对 SELECT 语句进行分析,获取优化器对当前查询的执行计划,以供开发人员针对相关 SQL 进行优化。在 SELECT 语句前加上 Explain 就可以查看到相关信息, 例如:
EXPLAIN SELECT * from user_info WHERE id < 300;
SELECT 查询的标识符. 每个 SELECT 都会自动分配一个唯一的标识符.
select_type 表示了查询的类型, 它的常用取值有:
查询的是哪个表,mysql 查询优化器执行的关联顺序并不和我们写 SQL 时关联的顺序一致,下面我们讲一下 Mysql 是如何对关联查询作优化的:
type 字段比较重要, 它提供了判断查询是否高效的重要依据依据. 通过 type 字段, 我们判断此次查询是全表扫描还是索引扫描等,type 类型的性能比较,通常来说, 不同的 type 类型的性能关系如下:
ALL < index < range < ref < eq_ref < const < system < NULL
# 因为表中backend_user是主键,所以子查询里最多可以选出一条数据,所以最外层查询的type是system,里层查询的type是const
explain select * from (select * from backend_user where id = 1) a;
# 虽然是都是范围查询,其实第二个查询时多个等值条件查询
# 对于第一个查询,mysql 无法再使用该列后面的其它查询索引了,而第二个则可以继续使用索引
select id from actor where id > 45 and class_id=3;
select id from actor where id in (44, 47, 48) and class_id=3;
此次查询中可能选用的索引,这些索引列是根据查询的列以及比较操作符来判断的,可能在后续的真实查询中没有用到也有可能
此次查询中确切使用到的索引,如果在 possible_keys 中没有出现而在 key 中出现,说明优化器可能出于另外原因比如选择覆盖索引,所以 possiable_keys 揭示了哪一个索引有助于高效进行查找,而 key 显示了采用哪一个索引可以最小化查询成本。
表示查询优化器使用了索引的字节数. 这个字段可以评估组合索引是否完全被使用, 或只有最左部分字段被使用到,比如我们建了一个组合索引(col1, col2),那么如下两条查询虽然用到的都是这个组合索引,但是对应的key_len的只是不一样的。key_len 显示了在索引字段中可能的最大长度,而不是数据使用的实际字节数
select * from table1 where col1 = 1;
select * from table1 where col1 = 1 and col2 = 2;
这一列显示了之前的表在 key 列记录的索引中查找值所用的列或者常量
rows 也是一个重要的字段. MySQL 查询优化器根据统计信息, 估算 SQL 要查找到结果集需要扫描读取的数据行数。这个值非常直观显示 SQL 的效率好坏, 原则上 rows 越少越好。
filtered 是在 MYSQL 5.1 中加进来的,在使用 EXPLAIN EXTENDED 时出现,表示此查询条件所过滤的数据的百分比,将 rows 除以 filtered 可以估算出整个表数据行数。
EXplain 中的很多额外的信息会在 Extra 字段显示, 常见的有以下几种内容:
当 Extra 中有 Using filesort 时, 表示 MySQL 需额外的排序操作, 不能通过索引顺序达到排序效果. 一般有 Using filesort, 都建议优化去掉, 因为这样的查询 CPU 资源消耗大。 但是 Explain 不会告诉你 Mysql 将使用文件排序还是内存排序:
-- 比如我们建立索引为:KEY `user_product_detail_index` (`user_id`, `product_name`, `productor`),那么如下两个查询
EXPLAIN SELECT * FROM order_info ORDER BY product_name; -- Using filesort,不能通过索引进行排序,需要优化
EXPLAIN SELECT * FROM order_info ORDER BY user_id, product_name;-- 无 Using filesort,通过索引进行排序,优化成功
"覆盖索引扫描", 表示查询在索引树中就可查找所需数据, 不用扫描表数据文件, 往往说明性能不错
这意味着 Mysql 服务器在存储引擎检索行后再进行过滤,一般出现 “Using where” 会受益于不同的索引
查询有使用临时表, 一般出现于排序, 分组和多表 join 的情况, 临时表可能是内存临时表或者文件临时表
在 Mysql 5.1 版本中引入了 EXPLAIN PARTITIONS 可以显示查询将访问的分区情况