项目场景:
java实现大数据量快速导入
问题描述
大家在项目中应该都会遇到导入的需求,如果导入数据量比较少的话,有的同学就会忽略掉性能的问题,前期可能发现不了问题,后面如果涉及到导入的数据比较多的时候,难免会出现导入很慢或者OOM的情况。
原因分析:
一次性导出大量数据肯定会有大量的I/O操作,占用cpu资源,同时也会给数据库带来巨大的压力,而且导入的过程中可能导致内存溢出的情况,最终服务宕掉的情况。
解决方案:
提示:此处上传关键代码:
1.先对总的集合进行分片处理,分片数量需要根据实际情况实际赋值,这样做的好处是可以通过多线程分批导入即缓解了线程的压力,提高了和数据库的交互性能,而且线程是并行的,极大的缩短最终的导入时间。
public void import(List<ImportDto> importVoList){
//todo 分批导入
int nums = importVoList.size() % batchInsertCount == 0 ? importVoList.size() / batchInsertCount : importVoList.size() / batchInsertCount + 1;
CountDownLatch countDownLatch = new CountDownLatch(nums);
List<List<ImportDto>> lists = ListUtil.partition(importVoList, batchInsertCount);
for (List<ImportDto> list : lists){
OpractorRunable opractorRunable = new OpractorRunable(list,countDownLatch);
Executors.newCachedThreadPool().execute(opractorRunable);
}
try {
countDownLatch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
2.通过创建个任务,方便我们通过Countdownlach来控制线程,至于Countdownlach的原理和使用方法大家不明白的可以度娘一下,自己尝试去敲一遍才会真正掌握它的用法。
private class OpractorRunable implements Runnable{
private List<ImportDto> importVoList;
private CountDownLatch countDownLatch;
private OpractorRunable(List<ImportDto> importVoList,CountDownLatch countDownLatch){
this.importVoList= importVoList;
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
saveOrUpdateBatch(importVoList);
countDownLatch.countDown();
}
}
好了,这是我工作中遇到的一些性能优化的点,跟大家分享下,也是做个笔记,毕竟学无止境,好记性不如敲一遍。哈哈。。。
注意:如果有想了解批量导出的可以参考我上一个作品,希望对大家有所帮助。