调了个方法导致接口变慢好多,真实原因有点坑。

前言

这篇文章是按照我的记忆梳理的,然后解决方法其实很简单,主要是梳理一下当时的排查思路,所以请大家多多指教。错误之处或表述不清楚的地方,欢迎评论指出或建议,感谢。

背景

事情发生在一个正常的下午,领导对我说:有项目组汇报说一个创建的接口变的比较慢,让我尽快排查一下。我一听,这个功能不是我写的,心里首先放松一下,那就排查吧!

验证线上

首先,当然是和领导确认,什么情况下,访问这个接口慢,因为有时候可能在某个特殊的场景下才会导致此类问题,或者是偶发情况,确定了这一点,也方便排查,然后我就按照领导说的,找到所属的数据页面,进行同样的操作。发现果然比较慢(这是我工作中学到的,不管别人怎么说,自己验证一遍),F12看了下,返回时间差不多快2s了,这个速度确实是有点慢的,因为这个添加的处理逻辑按理来说是不复杂的,不应该这么慢。

本地排查

接下来,就是排查的步骤,首先本地先启动一下,连接测试库看看是否有慢的问题,如果本地也慢,就比较方便一些,可以通过日志来打印每一部分花费的时间(我一般用StopWatch类),就可以知道哪里慢了。但是遗憾的是本地没有复现这种情况。

代码排查

既然无法复现,就只能看代码了,对比了下涉及到这个文件的提交记录,大概伪代码如下:

java 复制代码
...
...
String name = xxxService.getMember(name);
...
Project project = prjService.getProject(code);
...
project.getProjectId();
...
...

看见的第一眼,我直接忽略了这一段,觉得没啥问题啊,然后事实证明,事出反常必有妖。

最终原因

其实慢的原因就是我直觉忽略了的这一段代码中的Project project = prjService.getProject(code);,当我点进去后我才发现,里面别有洞天,我没法给大家复制代码,还是给大家一个伪代码:

java 复制代码
....
Project project = prjDao.getObject(code);
String pId = project.getProjectId();
List<Task> list = prjDao.queryTaskList(pId);
for (Task task : list){
    String taskId = task.getTaskId();
    Work w = prjDao.getObject(taskId);
    ....
    s = s.apend(w.getName());
}
project.setExtend(s);
....

以上代码存在的问题主要就是在for循环中进行对数据库的查询,如果list的长度很长的话,就会导致查询慢的问题,当时发现的时候真的是无语了,你如果有扩展,可以在方法中进行清晰的标识(比如:queryprojectExtend),并且代码也不必这么写,可以提取所有的taskId到一个list中,然后作为参数进行查询。

另外还有一个坑的点就是,其实原来的人调用这段方法本身其实就是为了拿一个project.getProjectId();,所以完全可以另外写一个简单获取的方法即可。

解决并验证

因为知道了原因,所以从数据库找了数据比较多的一个来进行复现,果然复现成功,也证明了问题就是出在这里。 首先把代码进行修复,修复后的伪代码如下:

java 复制代码
....
Project project = prjDao.getObject(code);
String pId = project.getProjectId();
List<Task> list = prjDao.queryTaskList(pId);
List<String> idList = list.getIdLIst(list);
List<Work> works = prjDao.queryObjectsByIds(idList);
for (Work task : list){
    s = s.apend(w.getName());
}
project.setExtend(s);
....

以上虽然也使用了for循环,但是内部只是做了字符串的拼接,也可使用Stream,会更简洁。 更改完后,继续测试该接口,发现是正常的。

思考总结

其实这次的问题很简单,没有涉及到高大上的一些问题来调整,要避免其实也很简单,调用其他人写的方法时,大概点进去观察一下。写方法的时候多想一下,是否会造成查询慢的问题,就可以了。

  • for循环查询这种情况,尽量避免。
  • 调用他人方法时需要知道内部大概的逻辑,切勿望文生义。
  • 不要想当然,觉得没问题就不排查。

致谢

感谢你的耐心阅读,如果我的分享对你有所启发或帮助,就给个赞呗,很开心能帮到别人。

相关推荐
苹果酱05671 小时前
一文读懂SpringCLoud
java·开发语言·spring boot·后端·中间件
掐指一算乀缺钱1 小时前
SpringBoot 数据库表结构文档生成
java·数据库·spring boot·后端·spring
计算机学姐3 小时前
基于python+django+vue的影视推荐系统
开发语言·vue.js·后端·python·mysql·django·intellij-idea
JustinNeil4 小时前
简化Java对象转换:高效实现大对象的Entity、VO、DTO互转与代码优化
后端
青灯文案14 小时前
SpringBoot 项目统一 API 响应结果封装示例
java·spring boot·后端
微尘85 小时前
C语言存储类型 auto,register,static,extern
服务器·c语言·开发语言·c++·后端
计算机学姐5 小时前
基于PHP的电脑线上销售系统
开发语言·vscode·后端·mysql·编辑器·php·phpstorm
码拉松6 小时前
千万不要错过,优惠券设计与思考初探
后端·面试·架构
白总Server6 小时前
MongoDB解说
开发语言·数据库·后端·mongodb·golang·rust·php
计算机学姐7 小时前
基于python+django+vue的家居全屋定制系统
开发语言·vue.js·后端·python·django·numpy·web3.py