一次真实的接口性能优化:从 2s 到 80ms 的排查过程

1 阅读3分钟

一次真实的接口性能优化:从 2s 到 80ms 的排查过程

很多性能优化文章都会讲方法论,但在实际工作中,真正有价值的是:
👉 你是怎么一步步定位问题的

这篇文章记录一个真实场景:
一个接口从平均 2s 响应时间,优化到 80ms 的全过程。


一、问题背景

某业务接口 /getUserList,用于分页查询用户列表。

初期数据量较小时一切正常,但上线 3 个月后:

  • 平均响应时间:2s+
  • 高峰期:偶尔超时
  • 数据量:约 50 万

二、第一步:确认瓶颈位置

先通过监控工具(如 Prometheus)查看:

  • CPU:正常
  • 内存:正常
  • QPS:不高

👉 初步判断:不是系统资源问题

然后加埋点日志,拆解耗时:

接口总耗时:2100ms
- 数据库查询:1800ms
- 数据处理:200ms
- 其他:100ms

👉 结论:问题在数据库


三、第二步:分析 SQL

核心 SQL:

SELECT * FROM user 
WHERE status = 1 
ORDER BY create_time DESC 
LIMIT 0, 20;

看起来很简单,但问题在于:

👉 没有合适索引

使用 EXPLAIN 分析后发现:

  • type: ALL(全表扫描)
  • rows: 500000+

四、第一次优化:加索引

增加复合索引:

CREATE INDEX idx_status_time 
ON user(status, create_time);

优化后:

  • 查询时间:1800ms → 400ms

👉 有提升,但还不够


五、第三步:发现隐藏问题(分页陷阱)

当分页页数变大时:

LIMIT 100000, 20;

MySQL 实际会:

👉 先扫描 100020 条,再丢弃前 100000 条

这就是经典的深分页问题。


六、第二次优化:改写分页方式

改为“基于游标”的分页:

SELECT * FROM user
WHERE status = 1 
AND create_time < last_time
ORDER BY create_time DESC
LIMIT 20;

👉 优化后:

  • 查询时间:400ms → 120ms

七、第四步:缓存优化

观察业务发现:

👉 用户列表数据变化频率不高

于是引入 Redis 缓存:

  • 热门分页直接走缓存
  • 设置合理过期时间

👉 优化后:

  • 接口整体:120ms → 80ms

八、最终结果对比

阶段响应时间
初始2100ms
加索引400ms
优化分页120ms
加缓存80ms

九、几个关键经验总结

1️⃣ 不要一上来就“优化代码”

先定位瓶颈在哪一层(数据库 / 代码 / 网络)


2️⃣ SQL 永远是性能核心

  • 索引是否合理
  • 是否存在全表扫描
  • 是否有深分页

👉 这些问题远比代码优化影响更大


3️⃣ 分页是高频坑

尤其是:

LIMIT offset, size

当 offset 很大时,性能会急剧下降。


4️⃣ 缓存不是万能,但很关键

适合场景:

  • 读多写少
  • 热点数据明显

5️⃣ 优化是“逐步逼近”的过程

很少有“一次到位”的优化,通常是:

👉 定位 → 优化一点 → 再定位 → 再优化


十、写在最后

很多人觉得性能优化很难,其实本质就三件事:

  1. 找到慢的地方
  2. 理解为什么慢
  3. 用合适的方法解决

真正拉开差距的,不是你会多少“技巧”,
而是你有没有完整做过一轮优化闭环。


如果你有类似的慢接口(SQL 或代码),可以贴出来,我可以帮你一起分析一下问题在哪。