记一次Spring Boot接口响应慢的排查过程

Alex Chen | 2026-07-23T15:52:00 | Java, Spring Boot

线上接口突然变慢,从2秒优化到50毫秒的全过程记录,包含N+1查询问题定位和MyBatis-Plus解决方案

# 记一次Spring Boot接口响应慢的排查过程 ## 背景 最近项目上线后,产品经理跑过来跟我说:“后台列表页怎么这么慢?等了好几秒才出来。”我一看监控,好家伙,一个列表接口平均响应时间2.3秒,这还了得。 ## 定位问题 ### 第一步:开启慢查询日志 ```sql -- 开启MySQL慢查询日志 SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1; -- 查看慢查询 SHOW VARIABLES LIKE 'slow_query%'; ``` 发现一个查询被执行了N次,典型的 **N+1查询问题** 。 ### 第二步:分析代码 ```java // 有问题的代码 - 循环中查询 List orders = orderMapper.selectList(null); for (Order order : orders) { // 每次循环都查一次数据库! User user = userMapper.selectById(order.getUserId()); order.setUserName(user.getName()); } ``` ## 踩坑记录 > 一开始我以为是索引问题,加了各种索引都没用,浪费了一下午。后来才发现根本原因是N+1查询。 ## 解决方案 使用MyBatis-Plus的批量查询 + Map缓存: ```java // 优化后 - 先批量查出所有用户 List orders = orderMapper.selectList(null); Set userIds = orders.stream() .map(Order::getUserId) .collect(Collectors.toSet()); // 一次查询所有用户 Map userMap = userService.listByIds(userIds) .stream().collect(Collectors.toMap(User::getId, u -> u)); orders.forEach(o -> o.setUserName( userMap.getOrDefault(o.getUserId(), new User()).getName() )); ``` ## 优化结果 | 指标 | 优化前 | 优化后 | |------|--------|--------| | 响应时间 | 2.3s | 50ms | | SQL次数 | 101次 | 2次 | ## 总结 遇到接口慢,别急着加索引,先看看是不是N+1查询。用 `p6spy` 或开启慢查询日志来定位问题,比瞎猜靠谱多了。

← Back to Blog