批量插入数据SQL写法,批量处理数据
今天在进行功能优化中遇到了碰到了一个功能,要处理10万条数据。在最开始开发时没有考虑那么多直接以单条数据来处理没有考虑到大批量数据的情况,导致功能不符合预期。那就优化呗。。。
首先考虑。减少与数据库的交互,把之前的一条一条查的代码优化为一次性全部查出,然后在批量处理数据。如果数据量太大(超2万)直接用SQL去批量处理有可能会报错,那是因为数据库单次处理数据的能力有限所以可以分批次处理。下面贴上示例;
**1:**批量插入数据的SQL ,xml文件编写
<!--批量插入-->
<insert id="insertBanch">
insert into "SZFMIMP"."T_STOCK_HISTORY_RESULT" (id,zccl,sbsj,sss,ssqh,crsj,kddm,kdmc,type,lspzid,lspzmc,qymc,qytyshxydm)
values
<foreach collection="list" item="item" index="index" separator=",">
( #{item.id},#{item.zccl},#{item.sbsj},#{item.sss},#{item.ssqh},
#{item.crsj},#{item.kddm},#{item.kdmc},#{item.type},#{item.lspzid},
#{item.lspzmc},#{item.qymc},
#{item.qytyshxydm}
)
</foreach>
</insert>
2: 查出的几万条数据分批次批量插入,时间会比单条处理效率快很多。亲测在没有优化前5万条数据处理需要大概3分钟左右。优化批量处理后处理时间缩短至5秒。
List<StockHistoryResultPo> list = stockInMapper.getFoodCount(lsxzList).parallelStream().map(tmp -> {
StockHistoryResultPo stockHistoryResultPo = new StockHistoryResultPo();
//数据转换:仅做参考
}).collect(Collectors.toList());
stockHistoryResultMapper.delete(new LambdaQueryWrapper<StockHistoryResultPo>().eq(StockHistoryResultPo::getType,2));
int count = 2000;
List<StockHistoryResultPo> list1 = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
list1.add(list.get(i));
if((count == list1.size()) || (i == list.size() - 1)){
//一次处理2000条数据,处理到最后一条数据跳出循环
int j = stockHistoryResultMapper.insertBanch(list1);
if(j > 0){
log.info("批量数据为:{}",JSON.toJSON(list1));
}
//清除集合
list1.clear();
}
}
3:以上处理方法优化
通过把大的list集合分片成若干大小的list分次执行批量插入。分片的方法用的是hutool中的分片方法,可以达到个上面方法同样的效果,代码更简洁。
int count = 2000;
List<List<TStockCityAll>> partition = ListUtil.partition(tStockCityAlls, count);
partition.forEach(tStockCityAllMapper::insertBatch);
内容仅为个人学习笔记记录,仅供参考!如有更好的思路和写法欢迎指导。