MySQL 慢查询怎么排查?

MySQL 慢查询排查遵循 "发现 → 定位 → 分析 → 优化 → 验证" 五步法:

  • 步骤①:开启慢查询日志,捕获慢 SQL。
  • 步骤②:查看慢查询日志,定位问题 SQL。
  • 步骤③:使用 EXPLAIN 分析执行计划。
  • 步骤④:根据分析结果优化(索引/SQL 改写)。
  • 步骤⑤:验证优化效果,对比执行时间。

一句话总结:开启慢查询日志定位问题 SQL,用 EXPLAIN 分析执行计划,针对性优化索引或改写 SQL,最后验证效果。

深度解析

一、开启慢查询日志

-- 1. 查看慢查询日志配置
SHOW VARIABLES LIKE '%slow_query%';
-- slow_query_log: OFF/ON(是否开启)
-- slow_query_log_file: 慢查询日志文件路径

-- 2. 查看慢查询阈值(默认 10 秒)
SHOW VARIABLES LIKE 'long_query_time';

-- 3. 动态开启慢查询日志(重启失效)
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 1;  -- 设置为 1 秒

-- 4. 是否记录没走索引的 SQL
SHOW VARIABLES LIKE 'log_queries_not_using_indexes';
SET GLOBAL log_queries_not_using_indexes = ON;

配置文件方式(永久生效):

# my.cnf
[mysqld]
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = ON

关键参数说明:

  • slow_query_log:是否开启慢查询日志
  • long_query_time:慢查询阈值,超过该时间的 SQL 会被记录(单位:秒,可精确到微秒)
  • log_queries_not_using_indexes:是否记录没走索引的 SQL(即使很快)
  • min_examined_row_limit:扫描行数少于此值不记录(避免记录简单查询)

二、定位慢查询 SQL

常用命令:

# 使用 mysqldumpslow 分析慢查询日志
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log

# 输出示例
Count: 5  Time=10.23s  Lock=0.00s  Rows=1000.0
SELECT * FROM orders WHERE create_time > '2024-01-01'
-- MySQL 5.7+ 使用 sys 库查询慢 SQL
SELECT
    query_id,
    LEFT(query, 100) AS query_preview,
    exec_count,
    avg_latency / 1000000 AS avg_ms,
    rows_examined,
    rows_sent
FROM sys.statements_with_runtimes_in_95th_percentile
ORDER BY avg_latency DESC
LIMIT 10;

三、使用 EXPLAIN 分析执行计划

-- 基本用法
EXPLAIN SELECT * FROM orders WHERE user_id = 100;

-- MySQL 8.0+ 推荐使用 EXPLAIN ANALYZE(显示实际执行时间)
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 100;

EXPLAIN 输出字段详解:

type 访问类型性能排序:

实战案例分析:

-- 案例 1:全表扫描(需要优化)
EXPLAIN SELECT * FROM orders WHERE amount > 100;
-- type: ALL, key: NULL, rows: 1000000
-- 优化:给 amount 加索引

-- 案例 2:索引范围扫描(较好)
EXPLAIN SELECT * FROM orders WHERE user_id = 100;
-- type: ref, key: idx_user_id, rows: 50
-- 已经走了索引

-- 案例 3:覆盖索引(最优)
EXPLAIN SELECT user_id, status FROM orders WHERE user_id = 100;
-- type: ref, key: idx_user_id, Extra: Using index
-- 不需要回表,性能最佳

四、常见慢查询场景与优化

优化实战示例:

-- 优化前:全表扫描 + 文件排序
EXPLAIN SELECT * FROM orders
WHERE status = 1
ORDER BY create_time DESC
LIMIT 100;

-- type: ALL, Extra: Using where; Using filesort
-- 优化:添加联合索引
CREATE INDEX idx_status_create_time ON orders(status, create_time);

-- 优化后:索引范围扫描 + 索引排序
-- type: ref, Extra: Using index condition
-- 优化前:索引失效(函数操作)
EXPLAIN SELECT * FROM orders
WHERE YEAR(create_time) = 2024;
-- type: ALL(索引失效!)

-- 优化后:改写为范围查询
EXPLAIN SELECT * FROM orders
WHERE create_time >= '2024-01-01'
  AND create_time < '2025-01-01';
-- type: range, key: idx_create_time

五、排查流程完整示例

posted on 2026-05-13 09:19  数据派  阅读(102)  评论(0)    收藏  举报