一、介绍:explain
二、执行计划的几个属性
1、id:
表示查询中select操作表的顺序,按顺序从大到小依次执行(不是表中的自增主键!)。id值相同执行顺序从上到下;id值不同时id值大的先执行。
2、select_type
这一列显示了对应行是简单还是复杂SELECT。取值如下:SIMPLE值意味着查询不包括子查询和UNION。查询有任何复杂的子部分,则最外层标记为PRIMARY。
(1)SIMPLE: 简单的 select 查询,不使用 union 及子查询。
(2)PRIMARY: 查询中如果包含任何子查询,那么最外层的 查询则被标记为primary;
(3)UNION: UNION 中的第二个或随后的 select 查询,不依赖于外部查询的结果集
(4) DERIVED: 衍生表,它一般是FROM列表中包含的子查询。用于 from 子句里有子查询的情况。 MySQL 会 递归执行这些子查询, 把结果放在临时表里。
(5)UNION RESULT:UNION的结果
(6)SUBQUERY:子查询中的第一个SELECT
(7)DEPENDENT SUBQUERY:子查询中的第一个SELECT,取决于外面的查询
(8) DERIVED:导出表的SELECT(FROM子句的子查询)
3、type :
该属性表示访问类型,有很多种访问类型。最常见的其中包括以下几种: ALL(全表扫描), index(索引扫描),range(范围扫描),ref (非唯一索引扫描),eq_ref(唯一索引扫描,),(const)常数引用, 访问速度依次由慢到快。其中 : range(范围)常见于 between and …, 大于 and 小于这种情况。由上至下效率越来越低
type字段的结果值,从好到坏依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
一般来说,好的sql查询至少达到range级别,最好能达到ref
(1)NULL:MySQL不访问任何表或索引,直接返回结果
(2)system: 表仅有一行(=系统表)。这是 const 连接类型的一个特例。
(3)const: 通过一次索引就能找到数据,一般用于主键或唯一索引作为条件的查询sql中。当 查询的表仅有一行时,使用 System。如
explain select * from test2 where id=1;
(4)eq_ref: 常用于主键或唯一索引扫描。从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用。和const的区别在于:
const只索引一次,而eq_ref主键和主键匹配,由于表中有多条数据,一般情况下要索引多次,才能全部匹配上。如
explain select * from test2 t1 inner join test2 t2 on t1.id=t2.id;
(5)ref: 常用于非主键和唯一索引扫描。
连接不能基于关键字选择单个行,可能查找 到多个符合条件的行。 叫做 ref 是因为索引要 跟某个参考值相比较。这个参考值或者是一个常数,或者是来自一个表里的多表查询的 结果值。
(6)ref_or_null: 如同 ref, 但是 MySQL 必须在初次查找的结果里找出 null 条目,然后进行二次查找。
(7)index_merge: 说明索引合并优化被使用了。
(8)unique_subquery: 在某些 IN 查询中使用此种类型,而不是常规的 ref:valueIN (SELECT primary_key FROM single_table WHERE some_expr)
(9)index_subquery: 在 某 些 IN 查 询 中 使 用 此 种 类 型 , 与unique_subquery 类似,但是查询的是非唯一 性索引
(10)range:
只检索给定范围的行,使用一个索引来选择 行。key列显示使用了哪个索引。当使用=、 <>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN 操作符,用常量比较关键字列时,可 以使用 range(一般该查询是最低忍受范围,一下两个就是慢的)。
(11)index: 全索引扫描,全表扫描,只是扫描表的时候按照索引次序 进行而不是行。主要优点就是避免了排序, 但是开销仍然非常大。
(12)all: 最坏的情况,从头到尾全表扫描(出现了说明需要优化了)。
提示 : 慢SQL是否走索引,走了什么索引,也就可以通过该属性查看了。
4、table :
输出数据行所在的表的名称
5、possible_keys
顾名思义,指出MySQL能使用哪些索引来优化查询,如果为空,说明没有可用的索引。查询所涉及的列上的索引都会被列出,但不一定会被使用,算是个提示作用!
6、key:
实际从 possible_key 选择使用的索引。 如果为 NULL,则没有使用索引。很少的情况 下,MYSQL 会选择优化不足的索引。这种情 况下,可以在 SELECT语句中使用 USE INDEX (indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制 MYSQL 忽略索引。如果有多个索引mysql选择的策略是:
(1)索引的选择性:选择性是指一个索引中不重复的值与表中总行数的比值。选择性越高,索引的效果越好。MySQL会根据选择性选择合适的索引。
(2)索引列的顺序:如果多个条件都能命中索引,那么MySQL会根据索引列的顺序选择合适的索引。一般来说,将选择性较高的索引列放在前面可以提高查询效率。
(3)索引覆盖度:索引覆盖度是指索引中包含的列是否满足查询的所有条件。如果一个索引可以完全覆盖查询的所有条件,那么MySQL可以直接使用该索引,而不需要再访问表数据,从而加快查询速度。
(4)索引合并:如果一个查询语句的条件无法完全命中单个索引,MySQL可以使用索引合并的方式来加速查询。索引合并是指将多个索引的结果进行合并,得到最终的查询结果。
7、key_len :
表示索引字段的最大可能长度,KEY_LEN的长度由字段定义计算而来,并非数据的实际长度,当 key 字段的值为 null时,索引的长度就是 null。在不损失精确性的情况 下,长度越短越好。注意,key_len的值可以告诉你在联合索引中 MySQL 会真正使用了哪些索引。
8、ref:
连接匹配条件,如果走主键索引的话,该值为: const, 全表扫描的话,为null值,表示哪些列或常量被用于查找索引列上的值。该表中所有符合检索值的记录都会被取出来和从上一个表中取出来的记录作联合。ref用于连接程序使用键的最左前缀或者是该键不是 primary key 或 unique索引(换句话说,就是连接程序无法根据键值只取得一条记录)的情况。当根据键值只查询到少数几条匹配的记录时,这就是一个不错的连接类型。 ref还可以用于检索字段使用=操作符来比较的时候。以下的几个例子中,MySQL将使用 ref 来处理ref_table,和eq_ref的区别是-用到的索引是否唯一性。
9、rows (关键):
扫描行数,也就是说,需要扫描多少行,才能获取目标行数,一般情况下会大于返回行数。通常情况下,rows越小,效率越高, 大部分SQL优化,都是在减少这个值的大小。注意: 理想情况下扫描的行数与实际返回行数理论上是一致的,但这种情况及其少,如关联查询,扫描的行数就会比返回行数大大增加)。
10、Extra :
该属性中包括执行SQL时的真实情况信息,如上面所属,使用到的是”using where”,表示使用where筛选得到的值,常用的有:“Using temporary”: 使用临时表 “using filesort”: 使用文件排序。
10.1、 Distinct:
在select部分使用了distinc关键字。MySQL发现第1个匹配行后,停止为当前的行组合搜索更多的行。
10.2、Using filesort:
表示按文件排序,一般是在指定的排序和索引排序不一致的情况才会出现。排序时无法使用到索引时,就会出现这个。
10.3、 Using temporary:
表示是否使用了临时表,一般多见于order by 和 group by语句。
内部临时表。例如:ORDER BY或GROUP BY中的字段都来自左连接非驱动表(第二张表),就会创建一个临时表了。
临时表是一种会话级别的数据库对象,它只存在于创建它的数据库连接活动期间。与常规的持久化表不同,临时表在连接关闭或服务器重启后自动消失。MySQL临时表从创建方式上可以分为两种:
(1)外部临时表:用户通过显式的命令执行create temporary table创建的临时表。
(2)内部临时表:与外部临时表对应,并不是用户使用显示命令创建的临时表,而是数据库优化器为了协助复杂SQL的执行而自行创建的临时表,用户可以通过explain命令,在Extra列中,看是否有Using temporary,如果有就是用了内部临时表。
内部临时表总共有三种存储方式:
(1)使用内存
需要存储数据量不超过配置项tmp_table_size与max_heap_table_size的值。
(2)先使用内存,再转化成磁盘文件
当内存无法满足内部临时表存储的数据量时,MySQL会将临时表从内存转到磁盘文件,如果临时数据量庞大可能会导致磁盘容量的异常占用。
(3)直接使用磁盘文件
使用SQL_BIG_RESULT 的修饰时会直接使用磁盘文件;另一种是临时表字段中存在 BLOB 或 TEXT 列时也会直接放弃使用内存临时表。
10.4、 Using index:
索引覆盖。表示是否用了覆盖索引,说白了它表示是否所有获取的列都走了索引。直接通过索引就可以获取查询的数据。
10.5、 Using where:
需要回行。在查找使用索引的情况下,需要回表去查询所需的数据
10.6、 Using sort_union、Using union、Using intersect:
这些函数说明如何为index_merge联接类型合并索引扫描。通过相乘EXPLAIN输出的rows列的所有值,可以粗略地知道MySQL必须检查多少行以执行查询。