MySQL性能优化之explain分析

MySQL 提供了explain 命令, 它可以对 SELECT 语句进行分析,并输出 SELECT 执行的详细信息, 以供开发人员针对性优化。深入了解MySQL基于开销的优化器,可以获得很多可能被优化器考虑到的访问策略的细节,以及当运行SQL语句时哪种策略预计会被优化器采用。explain命令用法十分简单, 在 SELECT 语句前加上explain就可以了。

mysql> explain select * from table1;
+----+-------------+--------+------+---------------+------+---------+------+------+-------+
| id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+--------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | table1 | ALL  | NULL          | NULL | NULL    | NULL |    4 |       |
+----+-------------+--------+------+---------------+------+---------+------+------+-------+
expain出来的信息有10列,分别是id、select_type、table、type、possible_keys、key、key_len、ref、rows、Extra。

一、 id:SELECT 查询的标识符. 每个 SELECT 都会自动分配一个唯一的标识符。
1)、 id相同时,执行顺序由上至下;
2)、 如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行;
3)、id如果相同,可以认为是一组,从上往下顺序执行;在所有组中,id值越大,优先级越高,越先执行。 

注意:根据笛卡尔积,数据量小的表优先查询

二、select_type:表示查询中每个select子句的类型
1) 、SIMPLE(简单SELECT,不使用UNION或子查询等)
2)、 PRIMARY(查询中若包含任何复杂的子部分,最外层的select被标记为PRIMARY)
3) 、UNION(UNION中的第二个或后面的SELECT语句)
4) 、DEPENDENT UNION(UNION中的第二个或后面的SELECT语句,取决于外面的查询)
5) 、UNION RESULT(UNION的结果)
6)、 SUBQUERY(子查询中的第一个SELECT)
7)、 DEPENDENT SUBQUERY(子查询中的第一个SELECT,取决于外面的查询)
8) 、DERIVED(派生表的SELECT, FROM子句的子查询)
9)、 UNCACHEABLE SUBQUERY(一个子查询的结果不能被缓存,必须重新评估外链接的第一行) 

三、table:查询涉及的表或衍生表,有时不是真实的表名字,看到的是derivedx(x是个数字,第几步执行的结果)

四、type:表示MySQL在表中找到所需行的方式,又称“索引类型”。type字段比较重要, 它提供了判断查询是否高效的重要依据。 通过 type 字段,我们判断此次查询是全表扫描还是索引扫描等。要对type优化的前提是有索引,常用的类型有: ALL, index,  range, ref, eq_ref, const, system(从左到右,性能从差到好),其中system、const只是理想情况,实际能达到ref>range。
1)、ALL:表示全表扫描, 这个类型的查询是性能最差的查询之一。 通常来说, 我们的查询不应该出现 ALL 类型的查询, 因为这样的查询在数据量大的情况下, 对数据库的性能是巨大的灾难。 如一个查询是 ALL 类型查询, 那么一般来说可以对相应的字段添加索引来避免。
2)、index: 表示全索引扫描(full index scan), 和 ALL 类型类似,只不过 ALL 类型是全表扫描, 而 index 类型则仅仅扫描所有的索引,而不扫描数据。index 类型通常出现在 所要查询的数据直接在索引树中就可以获取到, 而不需要扫描数据. 当是这种情况时, Extra 字段 会显示 Using index。
3)、range:表示使用索引范围查询, 通过索引字段范围获取表中部分数据记录。这个类型通常出现在 =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN() 操作中,其中in偶尔会失效,从而变成all。当 type 是 range 时, 那么 explain 输出的 ref 字段为 NULL, 并且 key_len 字段是此次查询中使用到的索引的最长的那个。
4)、ref:非唯一性索引,对于每个索引键的查询,返回匹配的行(0,多行)。
5)、eq_ref:唯一性索引,对于每个索引键的查询,返回唯一行数据(有且只有一行数据,不能多,也不能为0)。 select * from ...where name =...常见于主键或唯一索引。
6)、const:仅仅能查到一条数据的SQL,用于主键或唯一索引(类型与索引有关)。 const 查询速度非常快, 因为它仅仅读取一次即可。
7)、system: 只有一条数据的系统表,或衍生表只有一条数据的主查询。 这个类型是特殊的 const 类型。 

五、possible_keys:possible_keys 表示 MySQL 在查询时, 能够使用到的索引。 注意, 即使有些索引在 possible_keys中出现, 但是并不表示此索引会真正地被MySQL使用到。 MySQL 在查询时具体使用了哪些索引, 由key字段决定。 

六、Key:显示MySQL实际决定使用的键(索引)
如果没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。 

七、key_len:表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度(key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的),用于判断复合索引是否被完全使用。不损失精确性的情况下,长度越短越好。在utf8中,1个字符占3个字节,gbk1个字符2个字节,latin1个字符1个字节。如果索引字段可以为NULL,在会使用1个字节用于标识。
key_len 的计算规则如下:
字符串
char(n): n 字节长度
varchar(n): 如果是 utf8 编码, 则是 3 n + 2字节; 如果是 utf8mb4 编码, 则是 4 n + 2 字节。
数值类型
TINYINT: 1字节
SMALLINT: 2字节
MEDIUMINT: 3字节
INT: 4字节
BIGINT: 8字节
时间类型
DATE: 3字节
TIMESTAMP: 4字节
DATETIME: 8字节
字段属性: NULL 属性 占用一个字节. 如果一个字段是 NOT NULL 的, 则没有此属性。

八、ref:表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值 。

九、rows: 表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数 ,原则上 rows 越少越好。

十、Extra:该列包含MySQL查询的详细信息,有以下几种情况:
1)、Using where:需要回原表中查询。
2)、Using temporary:表示查询有使用临时表, 一般出现于排序, 分组group by和多表 join 的情况, 查询效率不高, 建议优化。 排序尽量对第一个表的索引字段进行,可以避免mysql创建临时表,这是非常耗资源的。查询哪些列,尽量group by那些列。
3)、Using filesort:MySQL中无法利用索引完成的排序操作称为“文件排序”, 表示 MySQL 需额外的排序操作, 不能通过索引顺序达到排序效果。 一般有 Using filesort, 都建议优化去掉, 因为这样的查询 CPU 资源消耗大。对于单索引,如果查找和排序是同一个索引,则不会出现,如果查找和排序不是同一个索引,则会出现。对于复合索引,不能跨列,符合最佳左前缀。避免where和order by按照复合索引的顺序使用,不能跨列或无序使用。
4)、Using join buffer:该值强调了在获取连接条件时没有使用索引,并且需要连接缓冲区来存储中间结果。如果出现了这个值,那应该注意,根据查询的具体情况可能需要添加索引来改进能。
5)、Impossible where:这个值强调了where语句会导致没有符合条件的行。
6)、Select tables optimized away:这个值意味着仅通过使用索引,优化器可能仅从聚合函数结果中返回一行
7)、Using index:"覆盖索引扫描", 表示查询在索引树中就可查找所需数据, 不用扫描表数据文件, 往往说明性能不错。 会对possible_keys有影响,如果有where则索引出现在possible_keys和key中,如果没有where则只在key中显示。

总结
1)、EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况
2)、EXPLAIN不考虑各种Cache
3)、EXPLAIN不能显示MySQL在执行查询时所作的优化工作
4)、部分统计信息是估算的,并非精确值
5)、EXPALIN只能解释SELECT操作,其他操作要重写为SELECT后查看执行计划。

参考资料
https://dev.mysql.com/doc/refman/5.5/en/explain-output.html

https://segmentfault.com/a/1190000008131735

你可能感兴趣的:(数据库)