如果想要查看QEP,只需要在SELECT语句前加上EXPLAIN关键字:
各列详解:
id:id列是在QEP中展示的表的连续引用。我的理解id也即等于执行顺序。
select_type: select_type提供了各种表示table列引用的使用方式的类型。最常见的值包括SIMPLE,PRIMARY、DERIVED和UNION。其他可能的值还有UNION RESULT、DEPENDENT SUBQUERY、 DEPENDENT UNION、UNCACHEABLE UNION 以及UNCACHEABLE QUERY
1. SIMPLE
不包含子查询和其他复杂语法的简单查询。
2.PRIMARY
这是为更复杂的查询而创建的首要表(也就是最外层的表)。
3. DERIVED
当一个表不是物理表时,被称作DERIVED。
table:table列是EXPLAIN命令输出结果中的一个单独行的唯一标识符。这个值可能是表名、表的别名或者一个为查询产生临时表的标识符,如派生表、子查询或集合。
示例:
table:item
table:<derivedN>
table:<unionN,M>
N和M是另一个table行的id值。
type:type代表QEP中指定的表使用的连接方式。以下是常用的几种连接方式,效率从上至下递减。当出现ALL的时候,应该考虑下是否需要优化。
・const 最多只有一行匹配
・system 这个是const的特例,当表只有一个row时会出现
・eq_ref 这个值表示从该表中会有一行记录被读取出来以和从前一个表中读取出来的记录做联合。例如a表的主键是id,b表的主键也是id,1:1对应,进行inner join查询。
・ref 这个值表示该表中所有符合检索值的记录都会被取出来和从上一个表中取出来的记录作联合。例如a表的主键是id,b表的主键是id和date,1:n对应,进行inner join查询。
・range 这个值表示所有符合给定范围值的索引行都被用到
・ALL 这个值表示需要一次全表扫描
possible_keys:指出优化器为查询选定的可用索引。为查询确定QEP的速度也会影响到查询的性能。如果发现有大量可能的索引,则意味着这些索引没有被用到。
key:优化器选择使用的索引。一般来说SQL查询中的每个表都仅使用一个索引。也存在索引合并的少数例外情况。
key_len:定义用于SQL语句连接条件的键的长度。可以用于确认索引有效性以及多列索引中用到的列的数目。
ref:标识用来进行索引比较的列或者常量。
rows:提供了所有存在于累计结果集中的行数目的MYSQL优化器估计值。查询中总的读操作数量是基于合并之前行的每一行的rows值的连续累计而得出,是一种嵌套行算法。以连接两个表的QEP为例。id=1的行rows=1,id=2的行rows=2,则读操作总数目为6。id=1的行rows=5,id=2的行rows=1,则对第一个表的5个累积量中每个都有一个读操作,总的读操作为10(5+5)
Extra:提供了不同种类MySQL优化器路径的一系列额外信息,以下为几个常见的类型
・Using Where 查询使用了where语句来处理结果。
・Using temporary 表示使用了内部临时表
・Using filesort 这是Order By语句的结果,是Mysql里一种速度比较慢的外部排序。可以通过选择合适的索引来改进性能。
・Using index 只需要使用索引就可以满足查询表的要求,不需要直接访问表数据。
・Using join buffer 强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间过程。
・Imposssible where 强调了where语句没有符合条件的行。例如:explain select * from user where 1=2
・Distinct 意味着找到第一个匹配行之后就会停止搜索其他的行
・filtered 给出一个百分比的值,和rows列的值一起使用,可以估计出和QEP中前一个表进行连接的行的数目。这一列只有在EXPLAIN EXTENDED语句中才会出现
・partitions 代表给定表所使用的分区。这一列只有在EXPLAIN PARTITIONS语句中才会出现
个人经验:
・优化查询速度首要想办法减少累计结果集的行数目(rows),可以通过索引、加上适当的where条件等方法。必要时将多个检索部分分成数个union all进行查询。
・type尽量保持在range以下,不要出现ALL
・possible_keys太多时需要检查删除不需要的索引,比如index(id)与符合索引index(id, date)重复。建立索引时也要考虑索引选择性,索引选择性差的字段可以不用建立索引。
・select_type出现DEPENDENT SUBQUERY需要考虑优化,子查询中的第一个SELECT,取决于外面的查询。关于这部分内容学习了一篇文章:http://www.cnblogs.com/zhengyun_ustc/archive/2013/11/29/slowquery3.html
・extra出现Using temporary时要考虑能否优化,比如groupby时出现,可以考虑用索引优化。
・extra出现Using filesort 时要考虑能否优化,比如groupby、orderby时出现,可以考虑用索引优化。
・extra出现Using join buffer时,可以考虑用索引优化。
・列在查询中使用函数时不会使用索引。
・in语句可以使用索引,但是也可以用exists优化,酌情考虑。同理not in和not exists
・like条件以%开头无法使用索引,例如like '%xxx',但是like 'xxx%'可以使用索引
・避免使用select *, 使用具体的列代替
・查询时给表加上适当的别名
・尽量减少嵌套查询