MySQL慢查询优化实战:从10秒到50毫秒的排查与解决思路

2026-05-18 码匠 数据库

在 Web 开发中,数据库查询性能往往是系统瓶颈的「重灾区」。一个看似简单的 SQL 查询,随着数据量增长可能从毫秒级变成秒级,甚至拖垮整个服务。本文通过一个真实案例,展示从发现慢查询到优化完成的完整流程。

一、发现问题:慢查询日志

首先确保 MySQL 开启了慢查询日志:

-- 查看是否开启
SHOW VARIABLES LIKE 'slow_query_log';
-- 设置阈值(超过 1 秒记录)
SET GLOBAL long_query_time = 1;
-- 查看日志位置
SHOW VARIABLES LIKE 'slow_query_log_file';

开启后,MySQL 会自动记录执行时间超过阈值的 SQL。这是优化的起点——你无法优化你不知道的问题。

二、分析工具:EXPLAIN 是你的好朋友

拿到慢 SQL 后,第一步是用 EXPLAIN 分析执行计划。重点关注这几个字段:

  • type:ALL(全表扫描)是最差的,要尽量优化到 ref 或 range
  • key:实际使用的索引,NULL 表示没走索引
  • rows:预估扫描行数,越小越好
  • Extra:出现 Using filesort 或 Using temporary 要警惕

三、常见优化手段

3.1 加索引(最直接有效)

-- 单字段索引
ALTER TABLE orders ADD INDEX idx_user_id (user_id);
-- 联合索引(注意字段顺序)
ALTER TABLE orders ADD INDEX idx_user_status_created (user_id, status, created_at);

联合索引遵循最左前缀原则:(a,b,c) 索引可以覆盖 a、ab、abc 三种查询,但不能覆盖 b 或 bc。

3.2 避免 SELECT *

只查需要的字段,减少数据传输和内存占用。

3.3 分页优化(深度分页问题)

-- 传统方式(offset 大时很慢)
SELECT * FROM orders ORDER BY id LIMIT 1000000, 20;
-- 优化方式(记住上一页最后一条的 ID)
SELECT * FROM orders WHERE id > 1000000 ORDER BY id LIMIT 20;

当 offset 达到百万级时,传统方式的性能会急剧下降。用 ID 游标可以避免大量回表。

3.4 子查询改 JOIN

子查询往往效率低于 JOIN,尤其是 IN 子查询涉及大量数据时。

四、真实案例:从 10 秒到 50ms

某电商系统的订单列表接口,数据量达到 500 万条时响应时间超过 10 秒。排查过程:

  1. EXPLAIN 发现:type=ALL,rows=5000000,全表扫描
  2. 加联合索引:(user_id, status, created_at),type 变为 ref
  3. 去掉 SELECT *:只取需要的 6 个字段
  4. 深度分页改为游标分页:LIMIT offset 改为 WHERE id > lastId
  5. 最终效果:10s → 50ms,提升 200 倍

五、进阶技巧

5.1 索引覆盖(Covering Index)

如果查询的字段全部包含在索引中,MySQL 可以直接从索引获取数据,无需回表。

5.2 FORCE INDEX 强制索引

当 MySQL 优化器选错索引时,可以用 FORCE INDEX 强制指定。

5.3 定期 ANALYZE TABLE

当数据量变化很大后,索引统计信息可能过时,导致优化器做出错误判断。

六、监控与预防

  • 使用 Prometheus + Grafana 监控慢查询数量趋势
  • 代码审查时要求所有新 SQL 都经过 EXPLAIN 检查
  • 建立 SQL 审核规范:禁止生产环境 SELECT *、禁止大表 JOIN 无限制等
  • 考虑引入 中间件如 ShardingSphere 做自动路由和优化

关于我们

如果你在数据库优化、网站建设、API 接口开发等方面需要帮助,尊云科技可以为你提供服务。

我们专注于网站建设、APP开发、小程序开发、PHP/Vue/UniApp开发、API接口、AI集成,拥有丰富的项目经验。

服务范围:

  • 网站建设与 SEO 优化
  • APP 开发(Android / iOS)
  • 小程序开发
  • PHP / Vue / UniApp 开发
  • API 接口与 AI 集成
  • EDM 邮件营销
  • BUG 修复与性能优化

联系方式: