简易分析慢 SQL 的流程和方法

分析慢 SQL 的核心是定位性能瓶颈(如全表扫描、索引失效、锁等待等),并针对性优化。以下是一套标准化的分析流程,从日志获取到根因定位,再到优化验证:

一、第一步:获取慢 SQL(开启并查看慢查询日志)

首先确保慢查询日志已开启,才能捕获到慢 SQL。

  1. 检查 / 开启慢查询日志 登录 MySQL 执行命令,查看当前配置:

    复制代码
    -- 查看是否开启(ON为开启,OFF为关闭)
    SHOW VARIABLES LIKE 'slow_query_log';
    -- 查看慢查询阈值(单位:秒,默认10秒,可根据业务调整为1秒)
    SHOW VARIABLES LIKE 'long_query_time';
    -- 临时开启(重启MySQL后失效,生产环境需在my.cnf中配置永久生效)
    SET GLOBAL slow_query_log = ON;
    SET GLOBAL long_query_time = 1; -- 阈值设为1秒,捕获更精细的慢SQL
  2. 查看慢查询日志内容 先找到日志路径:

    复制代码
    SHOW VARIABLES LIKE 'slow_query_log_file';

    再通过服务器命令查看日志(如 Linux):

    复制代码
    # 直接查看最新日志
    cat /var/lib/mysql/xxx-slow.log
    # 或用MySQL自带工具mysqldumpslow分析(按执行次数排序,取前10条)
    mysqldumpslow -s c -t 10 /var/lib/mysql/xxx-slow.log

二、第二步:用EXPLAIN分析 SQL 执行计划(核心步骤)

拿到慢 SQL 后,最关键的是通过EXPLAIN查看 MySQL 的 "执行思路",定位瓶颈。

1. 基本用法

在慢 SQL 前加EXPLAIN,例如:

复制代码
EXPLAIN SELECT * FROM user WHERE age > 30 AND name LIKE '%张三%';

执行后会输出 12 列关键信息,重点关注以下 6 列:

列名 核心含义 异常信号(需优化)
id SQL 执行顺序(数字越大越先执行,相同则按从上到下顺序) 无异常,但需理解多表关联时的执行逻辑
select_type 查询类型(如 SIMPLE = 简单查询、SUBQUERY = 子查询、JOIN = 关联查询) 出现ALL(全表扫描)、filesort(文件排序)、using temporary(临时表)
table 当前行正在访问的表 无直接异常,但需结合其他列判断
type 表的访问方式(性能从好到差:system > const > eq_ref > ref > range > index > ALL 出现ALL(全表扫描,数据量大时必慢)、index(全索引扫描)
key 实际使用的索引(NULL表示未使用索引) NULLtypeALL(未走索引)
Extra 额外执行信息(最能暴露问题的列) 包含Using filesort(需优化排序)、Using temporary(需优化临时表)、Using where(过滤在内存完成,无大问题)
2. 常见EXPLAIN异常及原因
  • 异常 1:type=ALL(全表扫描) 原因:未建索引、索引失效(如LIKE '%xx'、函数操作索引列、类型不匹配)。
  • 异常 2:Extra=Using filesort原因:排序字段未走索引,MySQL 需在内存 / 磁盘中手动排序(数据量大时极慢)。
  • 异常 3:Extra=Using temporary 原因:需创建临时表存储中间结果(如GROUP BY未走索引、多表关联排序未优化)。

三、第三步:补充分析工具(深入定位细节)

除了EXPLAIN,还可结合以下工具获取更具体的性能数据:

  1. EXPLAIN ANALYZE(MySQL 8.0.18 + 支持)EXPLAIN更精准,会实际执行 SQL 并返回真实的执行时间、行数等(注意:生产环境执行前需评估 SQL 是否会锁表或消耗资源):

    sql

    复制代码
    EXPLAIN ANALYZE SELECT * FROM user WHERE age > 30;
  2. 查看 SQL 执行时间和锁等待 通过SHOW PROFILE查看 SQL 执行的每个阶段耗时(需先开启):

    sql

    复制代码
    -- 开启 profiling
    SET profiling = ON;
    -- 执行慢SQL
    SELECT * FROM user WHERE age > 30;
    -- 查看最近一次SQL的执行详情
    SHOW PROFILE FOR QUERY 1; -- 1是SQL的ID,可通过SHOW PROFILES查看

    若耗时集中在Sending data(数据传输)或Waiting for table level lock(表锁等待),需进一步优化数据量或锁策略。

四、第四步:常见慢 SQL 根因及优化方向

根据上述分析,定位根因后针对性优化:

常见根因 优化方案
1. 未建索引 / 索引失效 - 给过滤条件(WHERE)、排序(ORDER BY)、关联(JOIN ON)字段建索引- 避免索引失效:不用LIKE '%xx'(改用LIKE 'xx%')、不函数操作索引列(如DATE(created_at) = '2024-01-01'改为created_at BETWEEN '2024-01-01 00:00:00' AND '2024-01-01 23:59:59'
2. 全表扫描(数据量大) - 建合适索引- 分表分库(如按时间分表、按用户 ID 分库)- 避免SELECT *,只查需要的字段(减少数据传输和内存消耗)
3. 排序 / 分组未走索引 - 给ORDER BY/GROUP BY的字段建联合索引 (如WHERE age >30 ORDER BY create_time,建索引(age, create_time))- 减少排序数据量(先过滤再排序)
4. 多表关联效率低 - 确保关联字段(JOIN ON)有索引- 小表驱动大表(如SELECT * FROM 小表 JOIN 大表 ON ...)- 避免LEFT JOIN时右边表的过滤条件写在WHERE中(会导致LEFT JOININNER JOIN
5. 事务 / 锁等待 - 缩短事务时长(避免在事务中执行非数据库操作,如 RPC 调用)- 用行锁(InnoDB)替代表锁,避免长事务占用锁资源

五、第五步:优化后验证

优化后需重新执行EXPLAIN和慢 SQL,确认:

  1. typeALL提升到ref/range等更优级别;
  2. key列显示使用了目标索引;
  3. Extra中无Using filesort/Using temporary
  4. 实际执行时间显著缩短(可通过EXPLAIN ANALYZE或业务监控确认)。

总结

分析慢 SQL 的核心流程:获取慢日志 → 用 EXPLAIN 看执行计划 → 定位根因(无索引 / 全表扫描 / 排序异常等) → 针对性优化 → 验证效果 。其中,EXPLAIN是最关键的工具,需重点掌握其输出列的含义和异常信号。

相关推荐
闲人编程2 小时前
深入理解Python的`if __name__ == ‘__main__‘`:它到底做了什么?
服务器·数据库·python·main·name·魔法语句
什么半岛铁盒3 小时前
C++项目:仿muduo库高并发服务器---------LoopThreadPool模块和TcpServer模块的实现
linux·服务器·c++·mysql·ubuntu
厚积薄发,积少成多3 小时前
深入解析 MySQL 时间类型:选择与应用
mysql
Lin_Aries_04214 小时前
容器化 Flask 应用程序
linux·后端·python·docker·容器·flask
angushine4 小时前
Windows版本PostgreSQL定时备份
数据库·windows·postgresql
roman_日积跬步-终至千里4 小时前
【系统架构设计(38)】数据库规范化理论
数据库·系统架构
YDS8294 小时前
MYSQL —— 约束和多表查询
数据库·mysql
The star"'4 小时前
MariaDB数据库管理
数据库·mariadb
鹏大师运维5 小时前
麒麟系统中修改 WPS 默认新建文件格式的方法
linux·操作系统·wps·docx·麒麟·word文档·excel文档