慢查询问题如何快速排查

wen IT资讯 32

本文目录导读:

慢查询问题如何快速排查

  1. 第一阶段:快速定位“元凶”SQL(秒级)
  2. 第二阶段:分析SQL执行计划(分钟级)
  3. 第三阶段:常见原因与快速对策
  4. 第四阶段:高压下的“救命”操作
  5. 总结:快速排查 SOP(标准操作流程)

快速排查慢查询问题,核心思路是先定位“元凶”SQL,再分析其执行计划,不要盲目加索引或改代码。

以下是分步骤的快速排查流程:

第一阶段:快速定位“元凶”SQL(秒级)

这是最关键的一步,需要直接从数据库层面抓取当前正在执行或近期执行缓慢的SQL。

方法1:查看当前正在运行的慢查询(最直接)

  • MySQL:
    -- 查看当前正在执行的所有线程,重点关注 Time 列(执行时间)
    SHOW FULL PROCESSLIST;
    -- 或者在 MySQL 5.7+ 中使用 performance_schema
    SELECT * FROM sys.session WHERE command != 'Sleep' AND time > 5 ORDER BY time DESC;
  • PostgreSQL:
    SELECT pid, now() - pg_stat_activity.query_start AS duration, query, state
    FROM pg_stat_activity
    WHERE state != 'idle' AND now() - pg_stat_activity.query_start > interval '5 seconds'
    ORDER BY duration DESC;

方法2:开启慢查询日志(事后分析)

  • MySQL:
    -- 查看当前是否开启及位置
    SHOW VARIABLES LIKE 'slow_query_log%';
    SHOW VARIABLES LIKE 'long_query_time';  -- 默认10秒,建议设为1秒或0.5秒
    • 生产环境建议临时开启,使用 mysqldumpslowpt-query-digest 分析日志文件,找到执行频率高、耗时长的SQL。

方法3:操作系统层面(最后一根稻草)

  • 如果数据库配置了连接池,且SQL都很快,但整体响应慢,可能是操作系统资源瓶颈
  • 常用命令: top(CPU/内存)、iostat -x 1(磁盘IO,重点关注 await、%util)、vmstat 1(上下文切换、等待队列)。

第二阶段:分析SQL执行计划(分钟级)

找到慢SQL后,使用 EXPLAIN 分析为什么慢。

  • MySQL:
    EXPLAIN [慢SQL];
  • PostgreSQL:
    EXPLAIN (ANALYZE, BUFFERS) [慢SQL];

关键指标(你需要立刻看什么):

  1. type 列(访问类型):
    • ALL全表扫描 —— 这是最需要警惕的,90%的慢查询源于此。
    • index:全索引扫描。
    • range:索引范围扫描(较好)。
    • ref/eq_ref/const:走索引且高效。
  2. rows 列: 预估扫描的行数,这个数字如果比实际返回的数据量大几个数量级(如扫描100万行返回10行),说明索引过滤性差。
  3. Extra 列(额外信息):
    • Using filesort文件排序,说明查询中有 ORDER BY 但未利用索引,需要专门排序。
    • Using temporary:用了临时表,常见于 GROUP BYDISTINCT 或子查询。
    • Using index):覆盖索引,回表少,性能好。
    • Using where(中性):需要回表检查过滤条件。

示例(MySQL):

-- 假设慢查询:
SELECT * FROM orders WHERE status = 'PENDING' ORDER BY create_time DESC;
-- EXPLAIN 可能看到:
-- type: ALL (全表扫描)
-- rows: 5000000
-- Extra: Using filesort (还需要排序)
-- 需要建立 (status, create_time) 的联合索引。

第三阶段:常见原因与快速对策

根据 EXPLAIN 结果,可以快速判断并给出解决方案:

现象(EXPLAIN中看到) 常见原因 快速对策
type=ALL, rows巨大 无索引或索引失效 立即创建索引(注意:大表加索引需谨慎,可能锁表,建议 pt-online-schema-change 或低峰期操作)。
Extra=Using filesort ORDER BY 字段无索引 在排序字段上建立索引,或将其包含在联合索引的最后。
Extra=Using temporary GROUP BYDISTINCT 导致临时表 优化查询逻辑,或为 GROUP BY 字段建立索引。
rows 大,但输出行很少 索引过滤性差(不是好索引) 重建索引(如复合索引字段顺序不当导致只使用了前缀字段)。
锁等待 SHOW OPEN TABLES WHERE In_use > 0 或查看 information_schema.INNODB_TRX 检查是否有长事务未提交。
磁盘IO高 全表扫描或大量数据排序刷盘 先加索引,如果不行,考虑硬件升级(换SSD)。

第四阶段:高压下的“救命”操作

如果数据库已经卡死,无法正常登录或执行 EXPLAIN

  1. 紧急止血(杀死慢查询线程):
    • MySQL:执行 SHOW PROCESSLIST; 找到 Time 很长的线程,用 KILL [线程ID]; 强制终止。
    • PostgreSQL:SELECT pg_terminate_backend([pid]);
  2. 临时降级:
    • 关掉耗资源的非核心查询(如报表、后台统计任务)。
    • 限流: 在应用层(如 Nginx、API 网关)对慢接口进行限流,防止雪崩。

快速排查 SOP(标准操作流程)

  1. 不能等: 立刻用 SHOW FULL PROCESSLISTtop 找到 最耗时 的 SQL 或 CPU/IO 最高 的进程。
  2. 不猜: 拿到 SQL 后,立刻执行 EXPLAIN
  3. 猛打: 如果看到 type=ALL,立刻评估加联合索引(ADD INDEX ...)。
  4. 后扫: 如果索引没问题,检查锁(SHOW ENGINE INNODB STATUS)、检查数据量(是否真的大到需要分库分表)、检查服务器资源(内存、磁盘)。

最核心的一句话: 80%的慢查询问题,根源都是“没有索引”或“索引失效”。 先抓 EXPLAINtyperows

抱歉,评论功能暂时关闭!