MySQL慢查询优化实战:从20秒到0.2秒的蜕变之路

一、被慢查询支配的恐惧

上周三凌晨2点(别问我为什么这个时间还在加班),我们的电商平台突然收到大量用户投诉:“购物车加载不出来!!” 我盯着监控大屏上持续飙红的数据库CPU曲线(已经冲到95%了!),手抖着打开了慢查询日志…

(真实案例警告)这个原本运行良好的订单查询接口,在促销期间响应时间从200ms暴涨到20秒!更可怕的是,这样的慢SQL在日志里像病毒一样疯狂复制,每秒钟触发上百次!

二、破案三板斧

1. 揪出真凶

-- 原始慢SQL
SELECT * FROM orders 
WHERE user_id = 12345 
  AND create_time > '2023-01-01'
  AND status IN (1,2,5)
ORDER BY update_time DESC 
LIMIT 10 OFFSET 0;

2. EXPLAIN大法好

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

执行计划显示:

  • 全表扫描(type=ALL)!!!
  • Using filesort(文件排序警告)
  • 扫描行数:2,348,761 行(窒息)

3. 慢查分析四象限

(掏出祖传分析模板)

1. 是否走索引? ❌
2. 是否合理使用索引? ❌
3. 是否存在不必要的数据? ✅
4. 执行计划是否最优? ❌

三、优化实战六连击

1. 索引手术刀

-- 创建复合索引(划重点)
ALTER TABLE orders ADD INDEX idx_query_opt (
  user_id, 
  status, 
  create_time, 
  update_time
);

避坑指南

  • 把等值查询条件放最前(user_id、status)
  • 范围查询字段置后(create_time)
  • 排序字段收尾(update_time)

2. 改写SQL语句

-- 优化后版本
SELECT id, order_no, total_amount 
FROM orders FORCE INDEX (idx_query_opt)
WHERE user_id = 12345 
  AND status IN (1,2,5)
  AND create_time > '2023-01-01'
ORDER BY update_time DESC 
LIMIT 10;

三大改进

  1. 指定强制索引(防优化器抽风)
  2. 减少返回字段(别用SELECT *!)
  3. 调整WHERE条件顺序(配合索引最左前缀)

3. 分页优化黑科技

-- 深度分页优化
SELECT * FROM orders 
WHERE id > 上一页最后ID 
ORDER BY id 
LIMIT 10;

当遇到LIMIT 100000,10这种需求时:

  • 改用ID区间查询
  • 配合前端滚动加载
  • 或者上Elasticsearch!

4. 连接查询的温柔一刀

(原罪SQL)

SELECT * FROM orders o
LEFT JOIN users u ON o.user_id = u.id
LEFT JOIN products p ON o.product_id = p.id
WHERE ...(十多个条件)

优化方案

  • 拆分成多个单表查询
  • 使用程序内存关联
  • 冗余必要字段到订单表

5. 函数操作的致命陷阱

-- 错误示范
WHERE DATE_FORMAT(create_time, '%Y-%m') = '2023-07'

正确姿势

WHERE create_time >= '2023-07-01' 
  AND create_time < '2023-08-01'

6. 终极武器:业务妥协

和产品经理大战三百回合后:

  • 取消"实时"查询要求 → 改异步队列
  • 砍掉非核心查询条件
  • 历史数据归档(3个月前订单移入历史表)

四、效果验证

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

优化后执行计划:

  • 索引范围扫描(type=range)
  • Using index condition
  • 扫描行数:236行(对比之前230万行!)
  • 执行时间:0.18秒 🚀

五、防慢查七大纪律

  1. EXPLAIN是亲爹:不看执行计划写SQL就是耍流氓
  2. 索引不是越多越好:每个索引都是UPDATE/DELETE的负担
  3. 字段精简主义:需要什么查什么,别用SELECT *
  4. 连接查询节制令:JOIN超过3个表就该报警了
  5. 分页深水炸弹:OFFSET超过1000就要考虑其他方案
  6. 定期慢查巡检:每天早上的第一杯咖啡应该配慢查日志
  7. 架构预防针:热点数据上缓存,复杂查询走搜索中间件

六、血泪经验谈

最近在优化一个统计报表时,发现个反直觉的现象:明明加了索引,查询还是慢。最后发现是字符集不一致导致索引失效!所以千万要注意:

-- 表字段是utf8mb4
ALTER TABLE users MODIFY COLUMN mobile VARCHAR(20) 
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 查询使用utf8
SELECT * FROM users WHERE mobile = '13800138000' 
COLLATE utf8_unicode_ci; -- 索引失效!

优化永无止境,记住:没有最好的SQL,只有最合适的执行计划。下次遇到慢查询时,深呼吸,打开EXPLAIN,让我们开始愉快的优化之旅吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值