需求背景:导出一个月的订单数据到excel,数据量150w左右。
当我听到这个需求的时候,打死项目经理的冲动异常强烈
问题难点:
- 1、数据从数据库查询,一次性查出肯定不行,所以要分页查询出所有数据,分页大小多少合适?
- 2、从数据库查询出的数据放哪里?150w条订单数据直接放内存里肯定不行,内存肯定受不了,太大了。
- 3、excel一个sheet页肯定放不下,因为一个sheet页只能存放1048576行数据,所以要分成多个sheet页存放,一个sheet页多少条数据合适?
解决方案:
经过反复测试和对比解决方案如下:
-
- 1、技术选型:阿里的easyexcel
-
- 2、数据库查询分页大小:5w
-
- 3、一个sheet页数据大小:5w
- 关键代码
int index = 0;
for (; index >= 0; index++) {
System.err.println("----------------------------");
dto.setPageSize(Long.valueOf(EXCEL_SHEET_MAX_ROW));
dto.setPageNo(Long.valueOf(index + 1));
System.err.println("线程号:" + Thread.currentThread().getName() + ",订单综合查询excel导出开始,页码:" + index + ",开始时间:\t\t\t" + dateformat.format(new Date()));
List<OrderChargeEXVo> orderChargeVoList = this.outExcelObtainOrderConsolidation(dto);
if (org.apache.commons.collections4.CollectionUtils.isEmpty(orderChargeVoList) || orderChargeVoList.size() == 0) {
break;
}
System.err.println("线程号:" + Thread.currentThread().getName() + ",订单综合查询excel导出开始,页码:" + index + ",结束时间:\t\t\t" + dateformat.format(new Date()) + ",订单数量:" + orderChargeVoList.size());
WriteSheet writeSheet = EasyExcel.writerSheet(index, ",综合订单" + index).head(OrderChargeEXVo.class).build();
excelWriter.write(orderChargeVoList, writeSheet);
System.err.println("线程号:" + Thread.currentThread().getName() + ",订单综合查询excel导出开始,页码:" + index + ",写入excel结束时间:\t" + dateformat.format(new Date()));
if (orderChargeVoList.size() < EXCEL_SHEET_MAX_ROW) {
break;
}
}
excelWriter.finish();
数据组装完成就可以进行下一步处理了。这一套下来,总耗时15min上下,文件大小350m左右,直接返回给web客户端吗?让客户直接等15min?谁有好的建议啊?