百万级数据处理难点
- 难点
①传统POI(Apache POI)框架,处理百万级数据量存在OOM(内存溢出)问题,并且效率低下;
②百万级数据通过select *一次查询结果耗时长,也是不可取;
③百万级数据导出到一个sheet页签中,效率低,打开Excel耗时长,体验不友好;
④百万级数据一行一行读取/写入Excel,此操作出现频繁IO;
⑤百万级数导入DB(数据库)每行循环插入也是不可取;
⑥百万数据如果通过Mybatis框架批量插入,即批量SQL循环插入,执行效率慢,也是不可取。
- 思路
❶原生的POI框架处理百万级数据解决内存溢出相当麻烦,使用阿里的一款封装POI工具即EasyExcel避免OOM问题;EasyExcel操作简单,执行效率高;
❷不能一次性查询百万级导出数据,可以分几次查询;通过分页插件,例如pagehelper分页插件,每次查询20w条,多次写入,实现百万级数据导出;
❸百万级数据分多个sheet页签写入,每个页签写入100w;
❹避免频繁IO操作,不能循环每行写入,通过分批查询结果写入;例如每次分批查询20w条写入;
❺导入时,通过一个集合临时存贮数据,待集合达到一定长度,批量插入数据库;
❻百万级数据导入时,不使用mybatis批量循环插入,使用更加高效的JDBC批量插入,配合事务完成批量插入数据库;即分批读取Excel百万级数据➕JDBC分批插入➕配合事务。
批注:
1. 数据量1w以内,mybatis批量插入
2. 数据量1w以上10w以下,JDBC批量➕配合事务;
3. 数据量10w以上,数据分批操作➕JDBC批量➕配合事务。
EasyExcel处理百万级数据导入
- 引入Maven坐标
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.1</version>
</dependency>
- 导入前期处理
public void import(MultipartFile file) {
InputStream inputStream = null;
try {
inputStream = file.getInputStream();
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ImportListener importListener = new ImportListener();
importListener.setParam("参数1","参数2");
EasyExcel.read(inputStream, T.class, importListener).sheet(0).doReadSync();
stopWatch.stop();
log.info("耗时: {}秒", stopWatch.getTotalTimeSeconds());
} catch (Exception e) {
log.error("导入失败:{}",e.getMessage());
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
- 监听器
import com.alibaba.excel.context.AnalysisContext;
import com