MySQL 高级 -- 性能优化之 Explain 分析 SQL
👨🎓作者:Java 学术趴
💌公众号:Java 学术趴
🚫特别声明:原创不易,未经授权不得转载或抄袭,如需转载可联系小编授权。
🙏版权声明:文章里的部分文字或者图片来自于互联网以及百度百科,如有侵权请尽快联系小编。微信搜索公众号 Java 学术趴联系小编。
☠️每日毒鸡汤:一件事你犹豫去不去做,那就是该立即动身做的。
1 Explain 查看执行计划
Explain + SQL : 查看执行计划包含的信息。(在正常的 SQL 语句之间加 Explain 查看执行计划信息)
3.5.1 执行计划包含的查询信息
不加\G 横向显示
加\G 纵向展示
1.2 表的读取顺序
id: select 查询的序列号(是一组数字),表示查询中执行 select 子句或操作的顺序。分为三种情况
id 相同,执行顺序由上至下。
id 不同,如果是子查询,id 的序号会递增,id 值越大优先级越高,越先被执行。
id 相同不同,同时存在。
1.3 数据读取操作的操作类型
select_type : 查询的类型。主要用于区别普通查询、联合查询、子查询等的复杂查询。
SIMPLE :简单的 select 查询,查询中不包含子查询或者 UNION。
PRIMARY : 查询中若包含任何复杂的子查询部分,这个类型代表最外层的。
SUBQUERY: 在 SELECT 或 WHERE 列表中包含了子查询。
DERIVED: 在 FROM 列表中包含的子查询被标记为 DERIVED(衍生),MySQL 会递归执行这些子查询,把结果放在临时表里。
UNION: 若第二个 SELECT 出现在 UNION 之后,则被标记为 UNION。若 UNION 包含在 FROM 子句的子查询中,外层 SELECT 将被标记为:DERIVED。
UNION RESULT: 从 UNION 表获取结果的 SELECT。
1.4 当前数据表名
table: 查询当前这一行数据是关于哪个表的。
1.5 访问类型排序
type: 显示查询使用的是何种类型。
从最好到最差一次是:system>const>eq_ref>ref>range>index>ALL
一般来说,得保证查询至少达到 range 级别,最好能达到 ref 级别。
system: 表只有一行记录(等于系统表),这是 const 类型的特例,平时不会出现,这个也可以忽略不计。
const: 表通过索引一次就能找到了,const 用于比较 primary key 和 unique 索引。因为只匹配一行数据,所以很快。如将主键置于 where 列表中,MySQL 就能将该查询转换为一个常量。
eq_ref: 唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。 常见于主键或唯一索引扫描。
ref: 非唯一性索引扫描,返回匹配某个单独值的所有行。 本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,它可能会找到多个符合条件的行,所以它应该数据查询和扫描的混合体。
range: 只检索给定范围的行,使用一个索来选择行。 key 列显示使用了哪个索引。一般就是在你的 where 语句中出现了 between、<、>、in 等的查询。这种范围扫描索引比全表扫描要好,因为是从某一个节点开始,而结束于某一个节点,不用全局扫描。
index: Full Index Scan ,index 和 ALL 区别为 index 类型只遍历所引树。这通常比 ALL 快,因为索引文件通常比数据文件小。(虽然 ALL 和 index 都是全读,但是 ALL 是从磁盘上读取原始数据,而 index 是读取全部的索引。)
all: Full Table Scan ,将遍历源数据的全表以找到匹配的数据。
1.6 显示可能应用在这张表中的索引
possible_keys :查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。如果没有则为 NULL。
1.7 实际用到的索引
key: 实际使用的索引,如果为 NULL,则没有使用索引。查询中若使用了覆盖索引,则该索引仅出现在 key 列表中。
我们真正使用的是 key 中存在的索引。
1.8 索引长度
key_len : 显示索引中使用的字节数,可通过该列计算查询中使用的索引长度。在不损失精确性的情况下,长度越短越好。
key_len 显示的值为索引字段的最大可能长度, 并非实际使用长度,即 key_len 是根据表定义计算而得,不是通过表内检索出来的。
1.9 索引对应的列
ref: 显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些劣或常量被用于查找查找索引列上的值。
1.10 花费行数
rows: 根据表统计信息及索引选用情况,大概估算出找出所需记录需要读取的行数。
1.11 额外数据
Extra: 不适合在其他列显示但十分重要的额外信息。
额外属性
Using filesort: 说明 MySQL 会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL 中无法利用索引完成的排序操作称之为“文件排序”。
这里创建的是一个聚合索引(col1,col2,col3),第二个 SQL 没有提示使用文件内部排序是因为使用列按照了索引的顺序(col1->col2->col3),但是第一个 SQL 没有使用到 col2,产生了一个断层,此时就需要 MySQL 内部自己进行一次文件排序。在使用 OEDER BY 排序的时候一定要符合聚合索引的顺序。
Using temporary: 使用了临时表保存中间结果,MySQL 在对查询结果排序时使用临时表。常见于排序 ORDER BY 和 分组查询 GROUP BY。
这里创建的是一个聚合索引(col1,col2),第二个 SQL 在 GROUP BY 的时候没有按照聚合索引的顺序,导致排序和分组都会提示相应的错误,一定要按照索引的顺序进行分组和排序。
Using index: 表示相应的 select 操作中使用了覆盖索引(Covering Index) ,避免访问了表的数据行,效果不错。如果同时出现了 using where,表示索引被用来执行索引键值的查找。如果没有同时出现 using where ,表示索引用来读取数据而非执行查找动作。
覆盖索引(Covering Index) : 就是 select 的查询的列从索引中就可以获取到,而不必去读取表中的原始数据,MySQL 可以利用索引返回 select 列表中的字段,而不必根据索引再次读取数据文件,换句话说: 查询列要被索引覆盖。
Using where: 说明使用了 where 过滤。
Using join buffer: 说明使用了表连接缓存。
impossible where: where 子句中的值总是 false,不能用来获取任何元组。(就比如找一个人,给定的查询条件,性别既是男性又是女性)
版权声明: 本文为 InfoQ 作者【Java学术趴】的原创文章。
原文链接:【http://xie.infoq.cn/article/966509c03439832b9c4f8ccdf】。文章转载请联系作者。
评论