性能提升 50%!记一次真实生产环境下的 SQL 优化实战

一、背景说明

最近在维护一个线上业务系统时,发现某个核心接口响应时间明显变慢

  • 平均响应时间:1.8s

  • 高峰期偶尔超过 3s

  • QPS 上来后,数据库 CPU 明显升高

该接口是一个列表查询接口,调用频率高,已经影响到了用户体验,因此必须进行优化。


二、问题定位:慢在哪里?

1️⃣ 先看接口逻辑

接口主要做了一件事:
根据条件分页查询订单列表

核心 SQL 如下(已脱敏):

SELECT * FROM orders WHERE user_id = ? AND status = ? ORDER BY create_time DESC LIMIT 20 OFFSET 0;

表数据量情况:

  • orders 表:约 300 万条数据

  • 日增长:几万条


2️⃣ 使用 EXPLAIN 分析执行计划

EXPLAIN SELECT * FROM orders WHERE user_id = 10086 AND status = 1 ORDER BY create_time DESC LIMIT 20 OFFSET 0;

关键输出信息:

  • type: ALL

  • rows: 3000000

  • Extra: Using where; Using filesort

👉 全表扫描 + 文件排序

问题已经很明显了。


三、问题根因分析

❌ 主要问题有三个

1. 没有合适的索引
  • user_id

  • status

  • create_time

虽然单独建过索引,但SQL 用不到


2. 使用了 SELECT *
  • 查询了大量无用字段

  • 增加 IO 和网络传输成本


3. ORDER BY + LIMIT 在大数据量下性能差
  • Using filesort

  • OFFSET 越大,性能越差


四、优化方案设计

✅ 优化目标

  • 减少扫描行数

  • 让 SQL 命中索引

  • 避免 filesort

  • 尽量少查字段


五、具体优化步骤


1️⃣ 创建联合索引(最关键一步)

CREATE INDEX idx_user_status_time ON orders (user_id, status, create_time DESC);

索引设计原则:

  • 等值查询字段在前

  • 排序字段在最后

  • 符合最左前缀原则


2️⃣ 避免使用 SELECT *

原 SQL:

SELECT * FROM orders ...

优化后:

SELECT id, order_no, amount, status, create_time FROM orders WHERE user_id = ? AND status = ? ORDER BY create_time DESC LIMIT 20;


3️⃣ 再次 EXPLAIN 验证

EXPLAIN SELECT id, order_no, amount, status, create_time FROM orders WHERE user_id = 10086 AND status = 1 ORDER BY create_time DESC LIMIT 20;

关键变化:

  • type: range

  • rows: 几十条

  • Extra: Using index

👉 已经完全走索引


六、优化前后性能对比

指标优化前优化后
平均响应时间1.8s0.9s
峰值响应时间3s+1.2s
扫描行数300万几十
CPU 占用偏高明显下降

整体性能提升约 50% 以上


七、额外优化思路(进阶)

如果数据继续增长,还可以进一步优化:

🔹 1. 使用游标分页(避免 OFFSET)

WHERE create_time < ? ORDER BY create_time DESC LIMIT 20;

🔹 2. 热数据和历史数据分表

🔹 3. 缓存热点数据(Redis)


八、总结

这次 SQL 优化让我再次意识到:

  • 慢 SQL ≠ SQL 写得复杂

  • 很多性能问题,本质是 索引设计问题

  • EXPLAIN 是排查 SQL 性能的第一工具

  • 联合索引顺序,决定 SQL 生死

一句话总结:

不是数据库慢,是 SQL 没写对。


九、最后

如果你也遇到过:

  • SQL 查询慢

  • 明明有索引却不生效

  • ORDER BY + LIMIT 很卡

  • 本文内容由AI辅助生成,经人工审核与编辑后发布。
  • 本文部分内容由AI生成,仅供学习与参考,请勿直接引用。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值