记录一次查询接口优化过程

前几天业务方反馈有一个接口查询时间,超过了1.5秒,不能忍了,让我看看,我看了下逻辑,对其中的一些逻辑进行了优化,也比较简单,这里做一个记录。

1.第一个改造就是

List<CallSaleInfoDto> callSaleInfoDtos = CallSaleInfoDto.fromEntity(callSaleInfoList, new CallSaleInfoDto());

这个方法本质上还是使用了
BeanUtils.copyProperties(dto, entity);
这个方法耗时特别长,200个数据耗时将近要1秒左右,后来改成 Lambda形式,200个时间缩短到10毫秒左右

List<CallSaleInfoDto> callSaleInfoDtos = callSaleInfoList.stream().map(
        callSale -> {
            CallSaleInfoDto dto = new CallSaleInfoDto();
            dto.setId(callSale.getId());
            dto.setUserId(callSale.getUserId());
            dto.setName(callSale.getName());
            dto.setProperty(callSale.getProperty());
            dto.setPrivateNum(callSale.getPrivateNum());
            dto.setBindTel(callSale.getBindTel());
            dto.setWorkPhone(callSale.getWorkPhone());
            dto.setTeam(callSale.getTeam());
            dto.setLogin(callSale.getLogin());
            dto.setBusy(callSale.getBusy());
            dto.setDeleted(callSale.getDeleted());
            dto.setSupplier(callSale.getSupplier());
            dto.setAxbSupplier(callSale.getAxbSupplier());
            dto.setCreateTime(callSale.getCreateTime());
            dto.setUpdateTime(callSale.getUpdateTime());
            dto.setBusyChangeTime(callSale.getBusyChangeTime());
            dto.setRrcCno(callSale.getRrcCno());
            return dto;
        }
).collect(Collectors.toList());

还有一个:

for (int i = 0; i < callSaleInfoDtos.size(); i++) {
    List<CallSaleDetail> callSaleDetailList = callSaleService.getDetailByCCid(callSaleInfoDtos.get(i).getId());
    callSaleInfoDtos.get(i).setCallSaleDetailList(callSaleDetailList);
}

这里遍历了每一个值,然后去查询数据库,这样如果有200个数据,就会跟数据库有200次的IO交互,对数据库的压力很大,并且耗时也很大,改成了下面这种

List<Integer> idList = callSaleInfoDtos.stream().map(s -> s.getId()).collect(Collectors.toList());
List<CallSaleDetail> callSaleDetailList = callSaleService.getDetailByCcIds(idList);
if (CollectionUtils.isEmpty(callSaleDetailList)) {
    return Response.ok(Collections.emptyList());
}
Map<Integer, List<CallSaleDetail>> callSaleDetailMap = callSaleDetailList.stream().collect(Collectors.groupingBy(CallSaleDetail::getCcId));
for (int i = 0; i < callSaleInfoDtos.size(); i++) {
    List<CallSaleDetail> detailList = callSaleDetailMap.getOrDefault(callSaleInfoDtos.get(i).getId(), Collections.emptyList());
    callSaleInfoDtos.get(i).setCallSaleDetailList(detailList);
}

改成了上面这种,首先拿到id列表,然后再数据库中使用in 查询一次数据库,将结果再使用Lambda 转换成Map,最后再根据map去匹配,在set进去最终的结果。

这里要注意的一点是 mysql对 in 也有要求,有的时候也会不走索引,但是这里最多就几百个,并且表中的总数据也就2000左右,问题不大。

结论:

1、改造前这个接口平均1.5秒,改造后 平均相应300毫秒,提升了5倍

那么问题来了,使用Lambda为啥会这么快呢?这值得研究一下:
java8特性lambda基本原理及性能分析:https://blog.csdn.net/heima201907/article/details/104983485
有时间看一下这篇文章,今天先写到这里

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值