当前位置: 首页 > 后端技术 > Java

百万数据秒级导出

时间:2023-04-01 22:11:33 Java

项目模拟百万数据导出,要求10秒内导出所有数据。项目使用springboot+mysql+mybatis+poi。项目的核心思想是数据分页+线程池。之所以使用线程池和数据分页,是因为数据导出涉及到IO操作。如果不使用线程池,串行时间会很长。同时数据量大,数据可能没有分页。会发生内存溢出。数据源:插入用户数据库的数百万数据:CREATETABLE`user`(`id`int(11)NOTNULL,`name`varchar(45)DEFAULTNULL,`createdTime`datetimeDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,`updatedTime`datetimeDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,PRIMARYKEY(`id`),KEY`index`(`id`))ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COMMENT='用户测试表';线程池数据量设计:合理配置线程池数量由于数据导出涉及大量IO,线程数=2*cpucoresfinalintnThreads=Runtime.getRuntime().availableProcessors();ExecutorServicepool=Executors.newFixedThreadPool(nThreads<<1);同时通过数据库查询语句添加where条件减少数据深度分页带来的性能损失selectid,`name`fromuserwhereid>#{param1}limit0,#{param2}另外,数据库优化,地址:MySQL核心参数优化包com.high.concurrency.currency02.service.impl;importcom.高.concurrency.currency02。domain.User;导入com.high.concurrency.currency02.mapper.UserMapper;导入com.highh.concurrency.currency02.service.IUserService;导入com.high.concurrency.currency02.util.ExcelUtil;导入com.high.concurrency.currency02.util.PageUtil;导入org.springframework.beans.factory.annotation.Autowired;导入org.springframework.stereotype.Service;importjava.util.List;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;@ServicepublicclassUserServiceImplimplementsIUserService{@AutowiredprivateUserMapperuserMapper;@OverridepublicStringexportData(){//获取可用线程数finalintnThreads=Runtime.getRuntime().availableProcessors();ExecutorServicepool=Executors.newFixedThreadPool(nThreads<<1);intpageSize=PageUtil.pageSize;//获取数据总量QuantityIntegercount=userMapper.getCount();//获取总页数inttotalPageCount=PageUtil.getTotalPageCount(count);//开始计时longstart=System.currentTimeMillis();intmaxId=0;for(intcurrentPageNum=0;currentPageNumuserList=userMapper.selectPage(maxId,pageSize);maxId=userList.get(userList.size()-1).getId();intfinalCurrentPageNum=currentPageNum;Runnablerun=newRunnable(){@Overridepublicvoidrun(){ExcelUtil.createExcel(finalCurrentPageNum,userList);if(finalCurrentPageNum==(totalPageCount-1)){System.out.println("导出数据到excel,已花费"+(System.currentTimeMillis()-start)+"ms");}}};池.执行(运行);}返回“确定”;}}操作效果如下:代码地址:github