前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >第 52 期:根据 EXPLAIN EXTRA 栏提示进行优化(四)

第 52 期:根据 EXPLAIN EXTRA 栏提示进行优化(四)

作者头像
爱可生开源社区
发布于 2025-03-13 13:38:43
发布于 2025-03-13 13:38:43
5500
代码可运行
举报
运行总次数:0
代码可运行

作者:杨涛涛,爱可生技术专家。

爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

1Using filesort

Using filesortMySQL 执行计划 EXTRA 栏里最为常见的提示之一,表示 MySQL 要执行这条 SQL 必须要做一个排序的消耗。

一般出现在强制按照某个字段排序,并且没有使用索引字段的有序性特征场景。

举个例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(mysql)>desc select * from t1 order by r1 limit 10\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 57918
     filtered: 100.00
        Extra: Using filesort
1 row in set, 1 warning (0.00 sec)

但并不是 EXTRA 栏提示 Using filesort 就代表必须优化,也得看业务场景。那如何判断呢?

对于只在内存里排序的业务场景,如果资源管够,同时并发不是很高,这种其实大可不必优化;而对于 内存不足,需要排序的记录溢出到磁盘上的业务场景,则必须优化。比如:排序字段加索引、或者修改 SQL 变为根据主键排序等等,必要时可以考虑把此类操作挪到应用端来处理。

2Using temporary

Using temporary 也是 MySQL 执行计划 EXTRA 栏里最常见的提示之一,表示执行这条 SQL 语句必须要隐式创建一张临时表来保存记录的中间状态。

一般当 SQL 语句里有 GROUP BY ,并且没有合适的索引时会有这个提示。

举个例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(mysql)>desc select count(log_date) from t1 group by r1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: ALL
...
         rows: 57918
     filtered: 100.00
        Extra: Using temporary; Using filesort
1 row in set, 1 warning (0.00 sec)

可以看到,type 栏为 ALL, Extra 栏里提示使用了临时表以及排序, 这是因为 MySQL 执行 GROUP BY 默认需要排序,但是分组字段又没有合适的索引。

SQL:select count(log_date) from t1 group by r1

等价于

SQL:select count(log_date) from t1 group by r1 order by r1

MySQL 8.0 的 GROUP BY 默认不排序,也就是说不会有隐式 ORDER BY 语句。针对这种简单场景,给 GROUP BY 字段加索引后,这个提示就会消除。

加完索引后的执行计划:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(mysql)>desc select count(log_date) from t1 group by r1 \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t1
   partitions: NULL
         type: index
possible_keys: idx_r1
          key: idx_r1
      key_len: 5
          ref: NULL
         rows: 57918
     filtered: 100.00
        Extra: NULL
1 row in set, 1 warning (0.01 sec)

以上例子都是最简单的 SQL,稍微复杂的 SQL 就不会是只加索引就可以消除临时表的。比如分组字段和排序字段不一样,或者说分组需要计算的临时列等等。这些场景得需要些复杂的优化措施,后期有专门的篇章来细讲这些内容,本篇就不深入了。

3Using join buffer

Using join buffer 表示 MySQL 对于两表做 JOIN 的 SQL ,JOIN KEY 不能用到索引时申请的一块内存区域。这块内存区域在 MySQL 里分别对应几种 JOIN 算法:

Using join buffer (Block Nested Loop)

Using join buffer (Block Nested Loop) 是块嵌套循环 JOIN,也是最慢的 JOIN。

举个例子:表 t1 和表 t2 做 INNER JOIN,JOIN KEY 上没有任何索引:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(mysql)>desc select * from t1 a join t2 b using(r2)\G
*************************** 1. row ***************************
          id: 1
 select_type: SIMPLE
       table: b
  partitions: NULL
        type: ALL
...
        rows: 9986
    filtered: 100.00
       Extra: NULL
*************************** 2. row ***************************
          id: 1
 select_type: SIMPLE
       table: a
  partitions: NULL
        type: ALL
...
        rows: 57918
    filtered: 10.00
       Extra: Using where; Using join buffer (Block Nested Loop)
2 rows in set, 1 warning (0.00 sec)

由于 JOIN KEY 没有索引,MySQL 对于这样的 JOIN 直接走最简单的嵌套循环,默认小表驱动大表,我们应该避免出现这样的场景(MySQL 最新版本对于这样的场景已经全部转为 HASH JOIN)。

Using join buffer (Batched Key Access)

Using join buffer (Batched Key Access) 是块嵌套循环的升级版,BKA 算法,一般和 MRR 一起用。

主要用在被驱动表的 JOIN KEY 上有索引的场景。利用索引的有序性,对表数据的随机 IO 转换为顺序 IO 的策略。

下面例子是对表 t1 字段 r2 加了索引后的执行计划:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(mysql)>desc select * from t1 a join t2 b using(r2)\G
*************************** 1. row ***************************
          id: 1
 select_type: SIMPLE
       table: b
  partitions: NULL
        type: ALL
...
        rows: 9986
    filtered: 100.00
       Extra: Using where
*************************** 2. row ***************************
          id: 1
 select_type: SIMPLE
       table: a
  partitions: NULL
        type: ref
possible_keys: idx_r2
         key: idx_r2
     key_len: 5
         ref: ytt.b.r2
        rows: 616
    filtered: 100.00
       Extra: Using join buffer (Batched Key Access)
2 rows in set, 1 warning (0.01 sec)

Using join buffer (hash join)

Using join buffer (hash join) 也是块嵌套循环的升级版,哈希连接算法,MySQL 版本需要大于 8.0 。

下面示例依然是表 t1t2 做连接,但是替换了JOIN KEY:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(mysql)>desc select * from t1 join t2 using(r3)\G
*************************** 1. row ***************************
          id: 1
 select_type: SIMPLE
       table: t2
  partitions: NULL
        type: ALL
...
        rows: 1000
    filtered: 100.00
       Extra: NULL
*************************** 2. row ***************************
          id: 1
 select_type: SIMPLE
       table: t1
  partitions: NULL
        type: ALL
...
        rows: 101745
    filtered: 10.00
       Extra: Using where; Using join buffer (hash join)
2 rows in set, 1 warning (0.00 sec)

MySQL 最新版里默认替代块嵌套循环连接为哈希连接, 如果被驱动表的 JOIN KEY 有索引,就会升级为 BKA 连接算法。

写到这里,对于执行计划 EXTRA 栏里常见的几种提示内容都已经做了示例说明,欢迎大家继续订阅。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-03-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 爱可生开源社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
第 51 期:根据 EXPLAIN EXTRA 栏提示进行优化(三)
爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。----
爱可生开源社区
2025/02/25
820
第 51 期:根据 EXPLAIN EXTRA 栏提示进行优化(三)
第 49 期:根据 EXPLAIN EXTRA 栏提示进行优化(一)
经过前面篇幅的持续阅读,相信大家对 MySQL 的执行计划已经有了一个较为深入的理解。本篇将对传统执行计划输出结果里的 Extra 栏进行逐步解析,从而使得大家更进一步的了解 MySQL 的 SQL 优化过程。
爱可生开源社区
2025/01/15
490
第 49 期:根据 EXPLAIN EXTRA 栏提示进行优化(一)
第 50 期:根据 EXPLAIN EXTRA 栏提示进行优化(二)
接着上一篇继续,依然是举例说明 EXPLAIN EXTRA 提示栏里的相关释义,这些提示将有助于我们更好的理解 SQL 语句在 MySQL 里的具体执行计划。
爱可生开源社区
2025/01/22
920
第 50 期:根据 EXPLAIN EXTRA 栏提示进行优化(二)
第 47 期:EXPLAIN TYPE 列的 JOIN 常见场景详解(上)
对于关系型数据库来说,表的设计 以及 SQL 的写法 尤为重要,占据性能的 90% 都不为过,所以这次专门针对这两大类知识领域,为您抽丝剥茧详细分析。
爱可生开源社区
2024/12/27
970
第 47 期:EXPLAIN TYPE 列的 JOIN 常见场景详解(上)
第 54 期:使用 JSON 格式的执行计划优化 SQL
前面几期我们讲过,EXPLAIN 可以得到一条 SQL 语句的执行计划,获得以下问题的参考数据:
爱可生开源社区
2025/04/10
900
第 54 期:使用 JSON 格式的执行计划优化 SQL
第 53 期:EXPLAIN 中最直观的 rows
MySQL 和大多数关系型数据库一样,SQL 语句执行计划的输出栏都有一行 rows,代表优化器执行这条 SQL 所需算子扫描的记录数,是优化器根据表和索引的统计信息数据评估出来的结果。
爱可生开源社区
2025/03/21
831
第 53 期:EXPLAIN 中最直观的 rows
MySQL通过索引优化-这里可能有你不知道的索引优化细节(二)
用执行计划分别测试一下union all、in和or,发现union all分两步执行,而in和or只用了一步,效率高一点。
行百里er
2020/12/02
9060
MySQL通过索引优化-这里可能有你不知道的索引优化细节(二)
第19期:索引设计(哈希索引数据分布与使用场景)
哈希索引显式应用主要存在于内存表,也就是 Memory 引擎,或者是 MySQL 8.0 的 Temptable 引擎。本篇的内容上都是基于内存表,MySQL 内存表的大小由参数 max_heap_table_size 来控制,其中包含了表数据,索引数据等。
爱可生开源社区
2021/01/13
3700
第 48 期:EXPLAIN TYPE 列的 JOIN 常见场景详解(下)
对于关系型数据库来说,表的设计 以及 SQL 的写法 尤为重要,占据性能的 90% 都不为过,所以这次专门针对这两大类知识领域,为您抽丝剥茧详细分析。
爱可生开源社区
2025/01/07
760
第 48 期:EXPLAIN TYPE 列的 JOIN 常见场景详解(下)
Extra(5)—mysql执行计划(五十一)
前面说了有type,simple表示普通查询或者连接查询,primary代表union最左边的select,union result代表union查询的临时表去重,所以union all没有去重功能,subquery代表in的子查询物化表的情况下才会出现,dependent subquery代表相关子查询,dependent union代表相关union查询,还有driverd子查询,from后面的,也需要物化,还有物化后转连接查询,这些都能看到mysql优化器是采用哪种查询方式。
用户9919783
2022/07/26
5340
Mysql索引使用案例分析
mysql能够在优化阶段分解查询语句,在执行阶段用不着再访问表或索引。例如:在索引列中选取最小值,可以单独查找索引来完成,不需要在执行时访问表
mingjie
2022/05/12
2.2K0
MySQL优化器和SemiJoin优化
背景 1. MySQL执行流程 MySQL的执行过程包括多个子阶段:语法分析、语义检查、逻辑优化、物理优化和执行。其中逻辑优化和物理优化统称为查询优化。一个查询优化器的输入是查询树,输出是查询执行计划。 逻辑优化也称为基于规则的查询优化(Rule Based Optimization,简称RBO)。主要是对查询进行逻辑上的等价变换,目的是通过这些变换提高查询的性能。 物理优化也称为基于代价的查询优化(Cost-based Optimization,简称CBO)。主要是通过一些模型,预测一个查询使用某种
腾讯云数据库 TencentDB
2019/05/16
1.4K0
MySQL优化器和SemiJoin优化
MySQL中explain中的结果字段介绍(三)
之前的文章中对于explain的数据结果中的字段已经进行了一部分介绍了,今天来说一说剩下的几个字段,为了防止忘记,先看看这个表结构:
AsiaYe
2019/11/06
2.3K0
第21期:索引设计(函数索引)
通常来讲,索引都是基于字段本身或者字段前缀(第 20 篇),而函数索引是基于字段本身加上函数、操作符、表达式等计算而来。如果将表达式或者操作符也看做函数的话,简单来说,这样的索引就可以统称函数索引。
爱可生开源社区
2021/02/26
8240
第21期:索引设计(函数索引)
技术分享 | EXPLAIN 执行计划详解(1)
爱可生 DBA 团队成员,擅长故障分析、性能优化,个人博客:https://www.jianshu.com/u/a95ec11f67a8,欢迎讨论。
爱可生开源社区
2021/02/26
2.5K0
技术分享 | EXPLAIN 执行计划详解(1)
mysql explain ref列_MySQL EXPLAIN详解
MySQL EXPLAIN详解:http://www.jianshu.com/p/ea3fc71fdc45
全栈程序员站长
2022/11/02
4.1K0
group by如何优化?
今天分享的内容是MySQL里面的group by语句,部分案例节选自极客时间的《MySQL45讲》,大家有兴趣可以购买相应课程进行学习,废话就不多说了,直接从例子开始吧。
AsiaYe
2020/06/06
2.4K0
一文看懂如何分析MySQL Explain(2/3)
⑨ range:如果使用索引获取某些范围区间的记录,那么就可能使用到range访问方法,比如:
程序员小强
2019/06/11
1.6K0
MySQL 8.0 OCP (1Z0-908) 考点精析-性能优化考点5:表连接算法(join algorithm)
我们知道对于Oracle的表连接,根据SQL连接条件主要支持如下三种连接方法(算法):
SQLplusDB
2023/08/17
6050
MySQL 8.0 OCP (1Z0-908) 考点精析-性能优化考点5:表连接算法(join algorithm)
MySQL优化必备之执行计划explain,索引基本知识,索引数据结构推演
这条SQL执行包含了PRIMARY、DEPENDENT SUBQUERY、DEPENDENT UNION和UNION RESULT
行百里er
2020/12/02
1.3K0
MySQL优化必备之执行计划explain,索引基本知识,索引数据结构推演
推荐阅读
相关推荐
第 51 期:根据 EXPLAIN EXTRA 栏提示进行优化(三)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验