Excel导入导出百万级数据
Excel百万级数据导入导出方案
本文使用EasyExcel工作,导出格式XLSX
1.生成测试数据
这里用到的是MYSQL 5.7.31 创建表语句
CREATE TABLE `ACT_RESULT_LOG` (`onlineseqid` int(11) NOT NULL AUTO_INCREMENT,`businessid` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,`becifno` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,`ivisresult` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,`createdby` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,`createddate` datetime DEFAULT CURRENT_TIMESTAMP,`updateby` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,`updateddate` datetime DEFAULT CURRENT_TIMESTAMP,`risklevel` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,PRIMARY KEY (`onlineseqid`)
) ENGINE=InnoDB AUTO_INCREMENT=1310694 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
这里插入测试数据
INSERT INTO `wjb`.`ACT_RESULT_LOG` (`onlineseqid`, `businessid`, `becifno`, `ivisresult`, `createdby`, `createddate`, `updateby`, `updateddate`, `risklevel`) VALUES (18179, 'test-01', '测试excel百万级数据导入导出', 'YES', '=======', '2022-10-11 10:18:11', 'wujubin', '2022-10-11 10:18:11', '1');-- 重复执行这条sql 一直执行数量大于100w 这里要注意了如果使用单个sheet 数据不能大于104w 这是excel的限制
INSERT INTO ACT_RESULT_LOG(`businessid`, `becifno`, `ivisresult`, `createdby`, `createddate`, `updateby`, `updateddate`, `risklevel`)
select `businessid`, `becifno`, `ivisresult`, `createdby`, `createddate`, `updateby`, `updateddate`, `risklevel` from ACT_RESULT_LOG
2.导出数据
依赖导入
<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.1.1</version>
</dependency>
导出注意点
- 一般需求导出excel数据量都比较少,不会引起OOM,因为数据都是放到内存中,如果达到百万级别很容易出现OOM,这里可以使用分页查询来处理。
- 如果数据量超过104w,就要写到多个sheet中,本文演示单个sheet导入导出百万数据
不分页查询导出
@GetMapping("/download")public void download(HttpServletResponse response) throws IOException {log.info("start====>{}",System.currentTimeMillis());long l = System.currentTimeMillis();// 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postmanresponse.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");EasyExcel.write(response.getOutputStream(), ActResultLogModel.class).sheet("模板").doWrite(actResultLogService.getList());log.info("end====>{}",System.currentTimeMillis()-l);}
结果耗时:40s. 但是很容易导致OOM,这里我设置的jvm内存比较大【不推荐】
分页查询导出
@GetMapping("/download2")public void download2(HttpServletResponse response) throws IOException {log.info("start====>{}",System.currentTimeMillis());long l = System.currentTimeMillis();OutputStream outputStream = null;try {outputStream = response.getOutputStream();ExcelWriter excelWriter = EasyExcel.write(outputStream, ActResultLogModel.class).build();// 这里注意 如果同一个sheet只要创建一次WriteSheet writeSheet = EasyExcel.writerSheet("模板").build();// 导出总数量int dataCount = actResultLogService.getDataCount();// 每次查询sizeint count = 200000;// 计算查询次数/页数int index = dataCount>count?dataCount/count+1:1;// 根据数据库分页的总的页数来for (int i = 0; i < index; i++) {List<ActResultLogModel> listByPage = actResultLogService.getListByPage(i*count, count);log.info("===>i:{},size:{}",(i+1),listByPage.size());excelWriter.write(listByPage, writeSheet);}}catch (Exception e){log.error("====>{}",e.getMessage());}// 这里注意 使用swagger 会导致各种问题,请直接用浏览器或者用postmanresponse.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setCharacterEncoding("utf-8");// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");log.info("end====>{}",System.currentTimeMillis()-l);}
耗时:37s. 不会导致OOM,且速度还要快些
导出的数据
3.导入数据
处理思路:导入文件后解析时需要分批操作【也是防止大量数据进入内存,导致OOM】
这里演示解析数据后,分批入库。入库也可换做做业务
这里需要了解一个点,easyExcel在解析excel的时候提供了一个监听器,只要实现它,读每行内容之后都会执行invoke方法
@Slf4j
public class UploadDataListener implements ReadListener<ActResultLogModel> {/*** 每隔BATCH_COUNT条存储数据库,实际使用中可以根据MYSQL服务器配置来配置,调试最优执行SQL大小,* 然后清理list,方便内存回收*/private static final int BATCH_COUNT = 50000;private List<ActResultLogModel> actResultLogModelList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);/*** 假设这个是一个DAO,当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。*/private final ActResultLogService actResultLogService;//如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来public UploadDataListener(ActResultLogService actResultLogService){this.actResultLogService = actResultLogService;}//这个每一条数据解析都会来调用@Overridepublic void invoke(ActResultLogModel actResultLogModel, AnalysisContext analysisContext) {actResultLogModelList.add(actResultLogModel);// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOMif (actResultLogModelList.size() >= BATCH_COUNT) {saveData();// 存储完成清理 listactResultLogModelList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);}}//所有数据解析完成了 都会来调用@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {saveData();log.info("===>解析完成!!");}//存储数据库public void saveData(){int i = actResultLogService.saveList(actResultLogModelList);log.info("====>{}",i);}
}
其中在配置分批次入库时,BATCH_COUNT参数设置需要根据MYSQL服务器配置来,过大可能会报You can change this value on the server by setting the ‘max_allowed_packet’ variable。设置MYSQL中配置文件my.cnf的max_allowed_packet参数就行,大于你报错提示的size就行。
其他具体代码
@PostMapping("/upload")
@ResponseBody
public String upload(MultipartFile file) throws IOException {log.info("start====>{}",System.currentTimeMillis());long l = System.currentTimeMillis();EasyExcel.read(file.getInputStream(), ActResultLogModel.class, new UploadDataListener(actResultLogService)).sheet().doRead(); // 这里初始化监听器就可以了log.info("end====>{}",System.currentTimeMillis()-l);return "success";
}
// 写入数据
public int saveList(List<ActResultLogModel> actResultLogModelList){// 最好判断 可能会报if (CollectionUtils.isEmpty(actResultLogModelList)) return -1;int i = actResultLogMapper.insertData(actResultLogModelList);log.info("数据入库数量:====>{}",i);return i;
}
// 分批入库@Insert({"<script>" +"<foreach collection=\"actResultLogModelList\" item=\"item\" separator=\";\">" +"INSERT INTO `wjb`.`ACT_RESULT_LOG2` (`businessid`, `becifno`, `ivisresult`, `createdby`, `createddate`, `updateby`, `updateddate`, `risklevel`) " +" VALUES (#{item.businessid}, #{item.becifno}, #{item.ivisresult}, #{item.createdby}, #{item.createddate}, #{item.updateby}, #{item.updateddate}, #{item.risklevel})" +"</foreach>" +"</script>"})int insertData(@Param("actResultLogModelList") List<ActResultLogModel> actResultLogModelList);
主要注意:OOM,根据服务器JVM大小来处理对于数据量
其他更多玩法:EasyExcel官方文档
Excel导入导出百万级数据相关推荐
- Excel怎么导出百万级数据
以前很久没碰到导出上10万数据到Excel.最近两年的业务有导出几十万数据的场景.Excel导出之前一直用NPOI导出的,NPOI的优势是不依赖Office环境.但是早期的NPOI导出操作Excel全 ...
- oracle百万级数据导入,用Perl从oracle导出百万级数据到excel
Perl从oracle导出百万级数据到excel excel 2007 可以存放1048576行.16384列的数据:excel 2003大概是65535行 我从oracle中导出30万行60列的数据 ...
- 使用POI导出百万级数据到excel的解决方案
使用POI导出百万级数据到excel的解决方案 参考文章: (1)使用POI导出百万级数据到excel的解决方案 (2)https://www.cnblogs.com/hxun/p/11419006. ...
- php导出1万条数据excel_PHP快速导出百万级数据到CSV或者EXCEL文件
前言: 很多时候,因为数据统计,我们需要将数据库的数据导出到Excel等文件中,以供数据人员进行查看,如果数据集不大,其实很容易:但是如果对于大数集的导出,将要考虑各种性能的问题,这里以导出数据库一百 ...
- 根据实体excel导入导出百万数据,可修改表头名称
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 表格导入导出实现效果展示 根据实体类导出模板 读取表格数据 导出数据为excel 进阶:修改表格导出的列头 controll ...
- 百万excel导入mysql_百万级xlsx表格导入数据库的实现方案
需求是这样的,供应商给到一份 xlsx 表格(144MB),里面刚好有 100w 行数据(11列).我需要把它们稍作处理后写入到 mysql 数据库 项目基于 Laravel,既然需要稍作处理,那我首 ...
- php oracle打印输出,php 连接oracle 导出百万级数据
1,我们一般做导出的思路就是,根据我们想要的数据,全部查询出来,然后导出来,这个对数据量很大的时候会很慢,这里我提出来的思想就是分页和缓冲实现动态输出. 2.普通的我就不说了,下面我说一下分页和内存刷 ...
- kettle分批处理大表数据_Kettle大量数据快速导出的解决方案(利用SQL导出百万级数据,挺快的)...
org.apache.commons commons-vfs2 2.0 org.scannotation scannotation 1.0.3 dom4j dom4j 1.6.1 pentaho-ke ...
- php导出1万条数据excel_实用!用PHP导出百万级大数据到Excel
实用!用PHP导出百万级大数据到Excel 作者:PHPYuan 时间:2018-07-31 03:41:41 关注我们的人 月薪都过万了 一.数据量分析 假设我们需要单日导入的数量为20W+ Exc ...
最新文章
- [译]Vulkan教程(04)基础代码
- 破天荒第一遭 安全公司因玩忽职守被客户告上法庭
- java编译器代码检查_java 命名代码检查-注解处理器
- WinCE 控制面板的创建
- NeurIPS2021 HRFormer:HRNet又出续作啦!国科大北大MSRA提出高分辨率Transformer,开源!...
- MySql之sql语句(自用)
- web server linux,GitHub - markparticle/WebServer: C++ Linux WebServer服务器
- 基金登记过户系统相关
- python模拟用户数据
- VSCode摸鱼插件,让工作更轻松
- itools苹果录屏大师_录屏大师限免|2019年1月最后一次苹果精选限时免费App 0131...
- 通过分析双色球历史中奖数据-增加机选号码中奖概率
- 中国出海50强,华为超越阿里得亚军,第一名居然是它?
- 考取FRM证书的三大好处,可能你还不知道
- c语言模拟走迷宫课程程序设计报告,《C语言程序设计》走迷宫游戏程序设计.doc...
- 宴会泡泡机市场前景分析及研究报告
- 解决Qualcomm Atheros QCA8172 有线网卡驱动问题
- 玩转 uniapp 全端开发
- PHY6252国产低功耗蓝牙5.2 SoC芯片智能手环/智能家居方案替代NRF52810
- 高仿糗事百科,完整版项目源码,带服务器部分
热门文章
- ppt怎么插入html代码,如何在PPT中插入html网.ppt
- 成都最最最牛逼的IT公司全在这了,来成都一起造富。。。
- SpringBoot全局异常处理
- 不论你技术多牛,这13条职场“潜规则”,越早知道越好!
- 畅游电驴/电骡(emule) 1.0 发布-下载网络资源的利器
- 【计量经济学导论】04. 多重共线性
- 城市公共交通周 9月18日郑州5条公交免费坐
- unity3D游戏开发十之粒子系统
- 新款文章,绝无仅有!微信语音aud文件转换为mp3格式
- JavaWeb-狂神系列