写点什么

MySQL 高级 -- 性能优化之 Explain 分析 SQL

作者:Java学术趴
  • 2022 年 10 月 11 日
    北京
  • 本文字数:2405 字

    阅读完需:约 8 分钟

MySQL高级--性能优化之Explain分析SQL

👨‍🎓作者:Java 学术趴

🏦仓库:GithubGitee

✏️博客:CSDN掘金InfoQ云+社区

💌公众号: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 keyunique 索引。因为只匹配一行数据,所以很快。如将主键置于 where 列表中,MySQL 就能将该查询转换为一个常量。

  • eq_ref: 唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。 常见于主键或唯一索引扫描。

  • ref: 非唯一性索引扫描,返回匹配某个单独值的所有行。 本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,它可能会找到多个符合条件的行,所以它应该数据查询和扫描的混合体。

  • range: 只检索给定范围的行,使用一个索来选择行。 key 列显示使用了哪个索引。一般就是在你的 where 语句中出现了 between、<、>、in 等的查询。这种范围扫描索引比全表扫描要好,因为是从某一个节点开始,而结束于某一个节点,不用全局扫描。

  • index: Full Index Scan ,index 和 ALL 区别为 index 类型只遍历所引树。这通常比 ALL 快,因为索引文件通常比数据文件小。(虽然 ALLindex 都是全读,但是 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 列表中的字段,而不必根据索引再次读取数据文件,换句话说: 查询列要被索引覆盖。


// t1表中存在 index_col1_col2 聚合索引select col1,clo2 from t1;// 我们只查询 col1和col2,并且这两个字段的数据都可以从索引中获取,此时叫做索引覆盖select col1 from t1;// 查部分字段也是可以的
复制代码


  • Using where: 说明使用了 where 过滤。

  • Using join buffer: 说明使用了表连接缓存。

  • impossible where: where 子句中的值总是 false,不能用来获取任何元组。(就比如找一个人,给定的查询条件,性别既是男性又是女性)



发布于: 刚刚阅读数: 6
用户头像

Java学术趴

关注

还未添加个人签名 2022.07.02 加入

还未添加个人简介

评论

发布
暂无评论
MySQL高级--性能优化之Explain分析SQL_10月月更_Java学术趴_InfoQ写作社区