AI改完代码功能明明正常,为什么接口反而越来越慢?N+1查询、重复请求与隐藏性能退化解析

使用 AI 修改真实项目时,有一种问题很容易被忽略:

功能已经改对了,测试也能通过,但接口却越来越慢。

比如原来一个接口响应只需要:

200ms

AI修改后功能完全正常,却变成:

800ms
1.5s
甚至更慢

代码没有明显报错,返回结果也正确。

真正发生的问题可能是:

功能正确了,但执行成本被悄悄放大了。

这类问题在数据量小时不明显,到了真实业务环境才容易暴露。


一、结果正确,不代表实现方式没有问题

假设需要查询100个用户对应的订单。

原来的代码可能是:

一次查询100个用户
+
一次批量查询订单

总共只需要少量数据库请求。

但AI重构后可能变成:

查询100个用户
↓
循环用户
↓
每个用户单独查询订单

于是数据库请求数量从几次变成:

1 + 100

功能完全正确。

只是接口速度明显下降。

这就是典型的:

N+1查询问题。


二、为什么AI容易产生N+1查询?

因为单看局部代码,这种写法非常自然:

for (const user of users) {
  const orders = await getOrders(user.id)
}

每一行逻辑都没有问题。

问题出在:

它会执行多少次。

如果只有3个用户,几乎感觉不到差别。

如果有:

100
1000
10000

个对象,数据库访问次数就会迅速增加。

所以检查AI代码时,除了问:

这段逻辑对不对?

还应该问:

这段逻辑会执行多少次?


三、重复请求也会制造隐藏性能问题

类似问题不只发生在数据库。

例如一个页面需要用户信息。

AI修改以后,三个组件分别调用:

getUser()

最终可能产生:

组件A → 请求一次
组件B → 请求一次
组件C → 请求一次

明明是同一份数据,却请求了三遍。

页面仍然可以正常显示。

但:

  • 网络请求增加;

  • 服务端压力增加;

  • 页面等待时间增加。

这种问题如果只检查最终页面,很容易被忽略。


四、重复计算同样会拖慢接口

例如代码里需要计算:

用户权限

原本只算一次。

AI重构后可能在多个判断里重复执行:

checkPermission()
checkPermission()
checkPermission()

如果这个函数内部还包含:

  • 数据库查询;

  • 文件读取;

  • 复杂计算;

成本就会进一步放大。

所以某些性能问题看起来只是:

多调用了几次函数。

实际上背后可能多执行了很多操作。


五、为什么测试通过也发现不了?

普通功能测试更关注:

输入
↓
输出是否正确

例如:

查询用户接口是否返回20条数据?

只要结果正确,测试就可能通过。

但测试并没有检查:

执行了多少条SQL?
调用了多少次接口?
花了多少时间?

所以会出现:

行为正确,但性能已经退化。

这也是为什么性能问题不能完全依赖普通单元测试发现。


六、小数据尤其容易掩盖问题

开发环境可能只有:

10条测试数据

即使发生N+1查询:

1 + 10

次SQL,也不会特别慢。

但生产环境可能一次处理:

1000条数据

查询次数就可能变成:

1 + 1000

这时候问题才突然明显。

所以AI修改涉及:

  • 列表;

  • 批处理;

  • 循环;

  • 关联查询;

时,最好特别检查:

数据量扩大以后成本会不会线性甚至更快增长。


七、怎么发现N+1和重复调用?

一个简单办法是看日志。

例如开启SQL日志后观察:

SELECT users...
SELECT orders WHERE user_id = 1
SELECT orders WHERE user_id = 2
SELECT orders WHERE user_id = 3
...

如果大量相似SQL不断出现,通常就值得检查。

同样也可以记录:

API调用次数
函数执行次数
接口耗时
数据库查询次数

有时候只需要比较:

修改前和修改后

就能很快发现问题。


八、批量查询通常比循环查询更合理

例如:

100个userId

与其循环执行:

getOrders(userId)

100次。

更合理的方案可能是一次性查询:

getOrdersByUserIds(userIds)

再在内存中按照用户进行分组。

这样数据库交互次数会明显减少。

当然具体实现要根据项目情况决定。

关键不是机械地“全部改成批量”。

而是先确认:

有没有重复访问同一种资源。


九、缓存也可能被AI无意绕过

有些项目原本已经有:

缓存
↓
数据库

AI为了快速完成新功能,可能直接调用底层数据库方法。

结果:

原来的缓存层没有走。

功能仍然完全正确。

但数据库压力突然增加。

所以AI新增调用路径时,还应该检查:

项目是不是已经有统一的数据访问入口?

如果有,最好优先复用原来的调用方式,而不是重新绕一条路径。


十、可以让AI主动做一次“性能影响检查”

完成代码修改以后,可以继续要求:

请检查本次修改可能带来的性能变化:

1. 是否在循环中增加数据库查询;
2. 是否重复调用同一个API;
3. 是否重复执行高成本函数;
4. 是否绕过已有缓存;
5. 数据量扩大100倍后是否会明显变慢;
6. 哪些地方适合改成批量处理。

这一步并不要求AI马上优化。

先找出潜在问题,再决定是否需要调整。


十一、一个实用的检查顺序

如果AI改完代码以后功能正常,但接口明显变慢,可以依次检查:

第一步:比较修改前后耗时。

确认性能下降是不是本次修改引起。

第二步:看数据库查询次数。

有没有N+1。

第三步:看网络请求次数。

有没有重复请求。

第四步:检查循环内部。

是否存在高成本操作。

第五步:检查缓存路径。

有没有绕开原有缓存。

第六步:用更大数据量重新测试。

确认性能问题是否随数据增长被放大。


最后

AI改完代码后功能正常,接口却越来越慢,本质上说明:

“代码正确”只解决了第一层问题。

真实项目还需要继续关注:

这段代码用了多少数据库查询、多少网络请求、多少重复计算,以及数据量增长以后成本会不会被放大。

尤其是:

循环
+
数据库
+
API
+
异步任务

同时出现时,更应该检查执行次数。

AI很容易写出局部完全正确的代码。

但工程质量还需要进一步确认:

它是不是用合理的成本完成了这件事。


持续更新 Codex、Claude Code 与大模型开发实战内容,更多深度内容和稳定订阅渠道欢迎搜索关注「孤狼GPT」。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值