在MySQL拿到一条慢SQL语句要如何优化?

ops/2025/3/4 0:57:02/

在工作的过程中,很多时候会发现执行业务逻辑的时候,某一条SQL语句执行得非常慢。这时候,要如何处理这条语句,如何判断语句慢的地方在哪里?

一、初级排查 EXPLAIN+慢SQL分析

MySQL官网用法:
https://dev.sql>mysql.com/doc/refman/8.4/en/explain.html
{EXPLAIN | DESCRIBE | DESC} ANALYZE [FORMAT = TREE] [schema_spec]
select_statement = [SELECT,UPDATE,DELETE,INSERT,REPLACE,TABLE]
schema_spec = {SCHEMA/DATABASE}
FORMAT = {JSON/TREE}

基础用法为:EXPLAIN SELECT * FROM XXX 执行语句的默认返回结果是tabular format

idselect_typetablepartitionstypepossible_keyskeykey_lenrefrowsfilteredExtra

字段解释:

1. id
定义: SELECT 查询的唯一标识符,每个 SELECT 子句分配一个独立 ID。
规则:
相同 ID:执行顺序从上到下(如简单 JOIN)。
不同 ID:数值越大优先级越高,越先执行(常见于嵌套子查询)。

2. select_type
定义: 查询类型,反映 SQL 的复杂度。
常见值:
SIMPLE:不含子查询或 UNION 的简单查询。
PRIMARY:最外层 SELECT(如含子查询的主查询)。
SUBQUERY:WHERE 或 HAVING 中的子查询。
DERIVED:FROM 子句中的子查询(临时表)。
UNION:UNION 操作的第二个或后续 SELECT。

3. table
定义: 当前查询涉及的表名或别名。
特殊情况:
<derivedN>:表示第 N 个子查询生成的临时表。
<unionM,N>:UNION 合并结果的临时表。

4. partitions
定义: 匹配的分区名称(仅当表使用分区时显示)。
示例: p0,p1 表示查询命中了分区 p0 和 p1。

5. type
定义: 表的访问方式,性能关键指标,从优到劣排序:
system > const > eq_ref > ref > range > index > ALL。
优化目标: 至少达到 range 级别,推荐 ref 或更高。

6. possible_keys
**定义:**理论上可能使用的索引列表(基于查询条件和表结构)。
注意: 可能为空(如全表扫描),但实际使用索引由 key 字段决定。

7. key
定义: 实际使用的索引名称。
特殊情况: NULL 表示未使用索引;PRIMARY 表示使用主键。

8. key_len
定义: 索引使用的字节数,反映索引字段的实际利用率。
规则:
数值越大,使用的索引字段越多。
根据字段类型和长度计算(如 INT 为 4 字节,可为 NULL 时 +1 字节)。

9. ref
定义: 与索引比较的列或常量。
常见值:
const:常量值(如 WHERE id=1)。
列名:关联查询中另一表的列(如 t1.col )。

10. rows
定义: MySQL 预估需要扫描的行数(基于统计信息)。
优化参考: 数值越小越好,若过大需检查索引或条件过滤。

11. filtered
定义: 经 WHERE 条件过滤后剩余行数的百分比。
示例: filtered=10% 表示预估 90% 数据被过滤。

12. Extra
定义: 额外执行信息,常见值及优化建议:
- Using filesort:需外部排序(建议添加索引优化 ORDER BY)。
- Using temporary:使用临时表(常见于GROUP BY,需优化查询或索引)。
- Using index:覆盖索引(无需回表,性能最佳)。
- Using where:WHERE条件过滤数据。

在以上的各个字段中,可以有限考虑分析Type与Extra这两个字段,如果无法分析出结果,再考虑其他字段。


除了使用基本的语法,还可以使用 EXPLAIN ANALYZE SELECT * xxx 这句语句会直接帮你分析语句的内容。
在这里插入图片描述

参数含义示例值说明
Table scan on user_login_logs执行计划类型:全表扫描(未使用索引,逐行遍历表数据)当前查询未命中索引,导致必须扫描整张表
cost=479916预估总成本:基于统计信息计算的资源消耗(包含CPU、IO等加权值成本单位是虚拟值,数值越大表示资源消耗越高
rows=4.68e+6预估扫描行数:优化器预测需要扫描的行数(基于数据分布统计)预计扫描468万行,与实际值(470万)误差约0.4%,说明统计信息较准确
actual time=0.0512…1585实际耗时:单位毫秒,0.0512为获取第一行的时间,1585为扫描全表总耗时首次数据返回极快,但全量扫描耗时1.585秒,可能引发性能瓶颈
rows=4.7e+6实际扫描行数:执行时真实处理的数据量实际扫描470万行,与预估基本一致,说明表体积较大
loops=1循环次数:该操作执行的总轮次(通常为1)单次全表扫描,无嵌套循环操作

全表扫描代价高
问题:未使用索引导致强制扫描全表,消耗大量I/O和CPU资源6。
验证:检查查询条件(如WHERE子句)是否涉及未索引字段,或索引选择性不足。

高成本与实际耗时匹配
现象:cost=479916与actual time=1585ms均表明操作代价极高。
根因:表数据量大(470万行),且无有效过滤条件或索引支持。

首次返回延迟低但总耗时长
特征:0.0512ms首行返回快,但全量处理需1.5秒,适合分批读取场景(如分页)。


二、慢查询日志分析

1、开启慢查询日志

show VARIABLES like '%slow_query_log%'
set GLOBAL slow_query_log = 1+-------------+-----+
|Variable_name      |value|
|slow_query_log     | ON  |
|slow_query_log_file| XXX |
+-------------+-----+show GLOBAL STATUS like '%Slow_queries%'
+-------------+-----+
|Slow_queries |  0  |
+-------------+-----+show GLOBAL VARIABLES like '%long_query_time%'
set GLOBAL long_query_time = 2
+-------------+-----+
|long_query_time |  2.0000  |
+-------------+-----+

2、捕获慢查询SQL

使用 sql>mysqldumpslow 工具统计高频慢 SQL

root > sql>mysqldumpslow -s t -t 10 /path/to/slow.log   

三、SHOW PROFILE 深度分析

1、开启性能分析:

show variables profiling;
set profiling = 1

2、执行目标SQL语句,查看耗时分布:

SHOW PROFILES;  
SHOW PROFILE CPU, BLOCK IO FOR QUERY [QUERY_ID];  

在这里插入图片描述


http://www.ppmy.cn/ops/162914.html

相关文章

算法(四)——位运算与位图

文章目录 位运算、位图位运算基本位运算异或运算交换两个数无比较返回最大值缺失的数字唯一出现奇数次的数唯二出现奇数次的数唯一出现次数少于m次的数 位运算进阶判断一个整数是不是2的幂判断一个整数是不是3的幂大于等于n的最小的2的幂[left, right]内所有数字&的结果反转…

MATLAB中asManyOfPattern函数用法

目录 语法 说明 示例 匹配尽可能多的模式实例 指定要匹配的最小模式数 指定要匹配的最小和最大模式数 asManyOfPattern函数的功能是模式匹配次数尽可能多。 语法 newpat asManyOfPattern(pat) newpat asManyOfPattern(pat,minPattern) newpat asManyOfPattern(pat,m…

优选算法的智慧之光:滑动窗口专题(一)

专栏&#xff1a;算法的魔法世界 个人主页&#xff1a;手握风云 目录 一、滑动窗口 二、例题讲解 2.1. 长度最小的子数组 2.2. 无重复字符的最长子串 2.3. 水果成篮 2.4. 将 x 减到 0 的最小操作 一、滑动窗口 滑动窗口算法又叫“同向双指针算法”&#xff0c;核心在于维…

shell脚本编程实践第4天

1 流程控制 1.1 for循环 1.1.1 嵌套循环 学习目标 这一节&#xff0c;我们从 基础知识、简单实践、小结 三个方面来学习。 基础知识 简介 这里的嵌套实践&#xff0c;与选择语句的嵌套实践基本一致&#xff0c;只不过组合的方式发生了一些变化。常见的组合样式如下&…

Rk3568驱动开发_点亮led灯(手动挡)_5

1.MMU简介 完成虚拟空间到物理空间的映射 内存保护设立存储器的访问权限&#xff0c;设置虚拟存储空间的缓冲特性 stm32点灯可以直接操作寄存器&#xff0c;但是linux点灯不能直接访问寄存器&#xff0c;linux会使能mmu linux中操作的都是虚拟地址&#xff0c;要想访问物理地…

C++二分图

二分图&#xff08;Bipartite Graph&#xff09;是一种特殊的图结构&#xff0c;其顶点可以分成两个互不相交的集合&#xff0c;使得每条边的两个顶点分别属于这两个集合。二分图在匹配问题&#xff08;如任务分配、婚姻匹配&#xff09;和网络流算法中有重要应用。 核心概念 …

《机器学习数学基础》补充资料:可逆矩阵的手工计算方法和总结

《机器学习数学基础》第2章2.3.1节阐述了可逆矩阵的定义、性质&#xff0c;并演示了Python中的计算函数及其应用。 本文是对书中这部分内容的补充&#xff0c;主要是说明如何用手工计算的方法得到常用矩阵的逆矩阵&#xff08;如果可逆&#xff09;。 若一个矩阵存在逆矩阵&am…

spring注解开发(Spring整合JUnit+MyBatis)(7)

目录 一、项目环境初始化。 &#xff08;1&#xff09;数据库与数据表。 &#xff08;2&#xff09;pom文件中的核心依赖坐标。 &#xff08;3&#xff09;实体类。 &#xff08;4&#xff09;service层。 &#xff08;5&#xff09;dao层。&#xff08;Mapper代理模式&#xf…