Java 近百万数据查询和导出共用时2分钟左右
特别感谢 https://www.cnblogs.com/barrywxx/p/10700283.html 提供的模板导出的技术和思路
测试环境:
1、jdk1.8 springboot mybatis mysql
2、70万条的数据34个字段,因业务需求是60万左右的数据量我这里只测试了70万的
技术和思路:
查询:采用流式查询,每次查询5万条数据
导出:采用模板的形式。用Excel的xml格式处理
代码展示:
controller层:
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import cn.stylefeng.guns.modular.zcManageTemp.service.XMLExportService;@Controller
@RequestMapping("/batchExport")
public class XMLExport {@Autowiredprivate XMLExportService XMLExportService;@ResponseBody@RequestMapping("/exprot")public void getData() throws Exception {long startTimne = System.currentTimeMillis();//模板对象。stringTemplate:只是一个标识,可随便命名StringTemplateGroup stGroup = new StringTemplateGroup("stringTemplate");// 写入excel文件头部信息//这里获取的模板路径是在classpath下的。默认是 resources下的StringTemplate head = stGroup.getInstanceOf("template/head");//创建导出的文件,如果存在会覆盖File file = new File("D:/test/yunda/output11.xls");PrintWriter writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream(file)));//对模板里的参数进行设置。我这里就直接设置了要导出的数据行数,列数在模板里写死了也可在这里设置。//如果数据行数以及列数小于你要导出的数据,则文件打不开。大于等于则无影响head.setAttribute("rows", "700100");writer.print(head.toString());writer.flush();// 写入excel文件数据信息StringTemplate body = stGroup.getInstanceOf("template/body");//分批次查询数据和导出数据.导出70万的数据,每次查询导出5万。如果服务器性能好,可以设置大点int size = 700000;int cs = 50000;if (size > 0) {int sang = size / cs;int yu = size % cs;for (int i = 0; i <= sang; i++) {List<Map<String, Object>> selectZCTestData = null;if(i == 0) {selectZCTestData = new ArrayList<Map<String, Object>>(50001);//第一行行头selectZCTestData.addAll(getMap());//注意:这里不要放到for循环外面,否者会出现每次循环都会有这一行的数据(具体原因没找到)}else {selectZCTestData = new ArrayList<Map<String, Object>>(50000);}long l1 = System.currentTimeMillis();//数据查询分页:此处用到了分流查询。否则会出现内存溢出。//如果这里用了分流查询但是服务器的jvm内存太小会导致卡死的问题。我在本地电脑跑的给了1024*3的大小Map<String, Object> map = new HashMap<String, Object>();map.put("star", i * cs);map.put("page", cs);if (i == sang) {if (yu > 0) {selectZCTestData.addAll(XMLExportService.selectZCTestData(map));}} else {selectZCTestData.addAll(XMLExportService.selectZCTestData(map));}System.out.println(i * cs);long l2 = System.currentTimeMillis();System.out.println("第" + i + "次查询用时=" + (l2 - l1));//数据写出if (selectZCTestData.size() > 0) {Worksheet worksheet = new Worksheet();//这个对现场是自己创建的,用于模板里worksheet.setRows(selectZCTestData);body.setAttribute("worksheet", worksheet);writer.print(body.toString());writer.flush();selectZCTestData.clear();selectZCTestData = null;}long l3 = System.currentTimeMillis();System.out.println("第" + i + "次导出用时=" + (l3 - l2));//清空数据XMLExportService.clearList();}}body = null;// 写入excel文件尾部:跟模板要匹配writer.print("</Table>");writer.print("</Worksheet>");writer.print("</Workbook>");writer.flush();writer.close();long endTime = System.currentTimeMillis();System.out.println("导出用时=" + ((endTime - startTimne) / 1000) + "秒");}private List<Map<String, Object>> getMap() {List<Map<String, Object>> retlist=new ArrayList<Map<String, Object>>();Map<String, Object> map = new HashMap<>();List<String> list = getList();list.forEach(p -> {map.put(p, p);});retlist.add(map);return retlist;}private List<String> getList() {List<String> list = new ArrayList<String>();list.add("code_id");list.add("zichan_code");list.add("ciji_num");list.add("pdzc_name");list.add("gongsi_code");list.add("bumen_code");list.add("zichan_name");list.add("zichan_nature");list.add("zichan_fenlei");list.add("zichan_guige");list.add("zichan_type");list.add("zichan_brand");list.add("supplier");list.add("laiyuan_way");list.add("zichan_value");list.add("zichan_zhejiu");list.add("zichan_netvalue");list.add("zichan_num");list.add("zichan_durable");list.add("baoxiuqi");list.add("jilaing_unit");list.add("zhuzichan");list.add("caigou_code");list.add("ruku_riqi");list.add("ruzhang_riqi");list.add("shebei_code");list.add("zeren_man");list.add("zeren_bumen");list.add("zichan_suoshu");list.add("zichan_cunfang");list.add("shiyong_man");list.add("shiyong_bumen");list.add("zichan_state");list.add("remark");return list;}
}
service层:
private List<Map<String, Object>> selectZCTestDataList = new ArrayList<Map<String, Object>>(50000);@Overridepublic List<Map<String, Object>> selectZCTestData(Map<String, Object> map) {//流式读取GxidResultHandler gxidResultHandler = new GxidResultHandler();try {this.baseMapper.selectZCTestData(map, gxidResultHandler);selectZCTestDataList.addAll(gxidResultHandler.getData());} finally {gxidResultHandler.end();}return selectZCTestDataList;}public void clearList() {selectZCTestDataList.clear();}
流式获取结果类:
import java.util.ArrayList;
import java.util.List;
import java.util.Map;import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;public class GxidResultHandler implements ResultHandler<Map<String, Object>> {// 存储每批数据的临时容器private List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(50000);int size = 0;@Overridepublic void handleResult(ResultContext<? extends Map<String, Object>> resultContext) {/** 回调处理逻辑 */list.add(resultContext.getResultObject());}public List<Map<String, Object>> getData() {return list;}// 这个方法给外面调用,用来完成最后一批数据处理public void end() {list.clear();}
}
dao层:
void selectZCTestData(Map<String, Object> map,ResultHandler<Map<String, Object>> handler);
worksheet:
package cn.stylefeng.guns.modular.zcManageTemp.controller;import java.util.List;
import java.util.Map;/*** 类功能描述:Excel sheet Bean**/
public class Worksheet {private String sheet;private int columnNum;private int rowNum;private List<Map<String,Object>> rows;public String getSheet() {return sheet;}public void setSheet(String sheet) {this.sheet = sheet;}public List<Map<String,Object>> getRows() {return rows;}public void setRows(List<Map<String,Object>> rows) {this.rows = rows;}public int getColumnNum() {return columnNum;}public void setColumnNum(int columnNum) {this.columnNum = columnNum;}public int getRowNum() {return rowNum;}public void setRowNum(int rowNum) {this.rowNum = rowNum;}
}
文件导出的模板:
head.st
<?xml version="1.0"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"xmlns:o="urn:schemas-microsoft-com:office:office"xmlns:x="urn:schemas-microsoft-com:office:excel"xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"xmlns:html="http://www.w3.org/TR/REC-html40"><DocumentProperties xmlns="urn:schemas-microsoft-com:office:office"></DocumentProperties><OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office"><AllowPNG/></OfficeDocumentSettings><ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel"><WindowHeight>8988</WindowHeight><WindowWidth>23040</WindowWidth><WindowTopX>32767</WindowTopX><WindowTopY>32767</WindowTopY><ProtectStructure>False</ProtectStructure><ProtectWindows>False</ProtectWindows></ExcelWorkbook><Styles><Style ss:ID="Default" ss:Name="Normal"><Alignment ss:Vertical="Center"/><Borders/><Font ss:FontName="等线" x:CharSet="134" ss:Size="11" ss:Color="#000000"/><Interior/><NumberFormat/><Protection/></Style></Styles><Worksheet ss:Name="sheet1"><Table ss:ExpandedColumnCount="34" ss:ExpandedRowCount="$rows$" x:FullColumns="1"x:FullRows="1" ss:DefaultRowHeight="13.8">
body.st
$worksheet:{$it.rows:{<Row><Cell><Data ss:Type="String">$it.code_id$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_code$</Data></Cell><Cell><Data ss:Type="String">$it.ciji_num$</Data></Cell><Cell><Data ss:Type="String">$it.pdzc_name$</Data></Cell><Cell><Data ss:Type="String">$it.gongsi_code$</Data></Cell><Cell><Data ss:Type="String">$it.bumen_code$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_name$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_nature$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_fenlei$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_guige$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_type$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_brand$</Data></Cell><Cell><Data ss:Type="String">$it.supplier$</Data></Cell><Cell><Data ss:Type="String">$it.laiyuan_way$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_value$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_zhejiu$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_netvalue$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_num$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_durable$</Data></Cell><Cell><Data ss:Type="String">$it.baoxiuqi$</Data></Cell><Cell><Data ss:Type="String">$it.jilaing_unit$</Data></Cell><Cell><Data ss:Type="String">$it.zhuzichan$</Data></Cell><Cell><Data ss:Type="String">$it.caigou_code$</Data></Cell><Cell><Data ss:Type="String">$it.ruku_riqi$</Data></Cell><Cell><Data ss:Type="String">$it.ruzhang_riqi$</Data></Cell><Cell><Data ss:Type="String">$it.shebei_code$</Data></Cell><Cell><Data ss:Type="String">$it.zeren_man$</Data></Cell><Cell><Data ss:Type="String">$it.zeren_bumen$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_suoshu$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_cunfang$</Data></Cell><Cell><Data ss:Type="String">$it.shiyong_man$</Data></Cell><Cell><Data ss:Type="String">$it.shiyong_bumen$</Data></Cell><Cell><Data ss:Type="String">$it.zichan_state$</Data></Cell><Cell><Data ss:Type="String">$it.remark$</Data></Cell></Row>}$
}$
结果展示:
0 第0次查询用时=2276 第0次导出用时=3575 50000 第1次查询用时=2090 第1次导出用时=4427 100000 第2次查询用时=2004 第2次导出用时=3705 150000 第3次查询用时=2229 第3次导出用时=3561 200000 第4次查询用时=2374 第4次导出用时=3502 250000 第5次查询用时=2816 第5次导出用时=3452 300000 第6次查询用时=3094 第6次导出用时=2871 350000 第7次查询用时=3085 第7次导出用时=3530 400000 第8次查询用时=2956 第8次导出用时=3148 450000 第9次查询用时=4073 第9次导出用时=3009 500000 第10次查询用时=4384 第10次导出用时=3163 550000 第11次查询用时=5824 第11次导出用时=3053 600000 第12次查询用时=4513 第12次导出用时=3689 650000 第13次查询用时=32630 第13次导出用时=3628 700000 第14次查询用时=0 第14次导出用时=0 导出用时=129秒 |
结束
从这次结果看,最后一次的查询耗时非常多,可能原因:1、jvm内存 2、主机性能 。总体来说勉强能用,但是还需要继续优化
Java 近百万数据查询和导出共用时2分钟左右相关推荐
- Java操作百万数据量Excel导入导出工具类(程序代码教程)
Java操作百万数据量Excel导入导出工具类(程序代码教程): # 功能实现1.自定义导入数据格式,支持配置时间.小数点类型(支持单/多sheet)(2种方式:本地文件路径导入(只支持xls.xls ...
- excel百万数据如何导入导出
前景 在项目开发中往往需要使用到数据的导入和导出,导入就是从Excel中导入到DB中,而导出就是从DB中查询数据然后使用POI写到Excel上. 写本文的背景是因为在工作中遇到了大数据的导入和导出,问 ...
- 百万数据的导入导出解决方案
300万数据的导入导出 前景: 在项目开发中往往需要使用到数据的导入和导出, 导入就是从Excel中导入到DB中,而导出就是从DB中查询数据然后使用POI写到Excel上. 写本文的背景是因为在工作中 ...
- c# mysql timeout expired_C#百万数据查询出现超时问题的解决方法
本文较为详细的讲解了C#百万数据查询出现超时问题的解决方法,分享给大家供大家参考之用.具体方法如下: 很多时候我们用C#从百万数据中筛选一些信息时,经常会出现程序连接超时的错误,常见的错误有很多,例如 ...
- AJAX for Java简单表数据查询实例
AJAX for Java简单表数据查询实例<?XML:NAMESPACE PREFIX = O /> AJAX WebShop 3对Java开发具有良好的支持,同时也提供了各种层次的后台 ...
- Java 百万数据秒级导出到Excel中
出自: 腾讯课堂 700多分钟干货实战Java多线程高并发高性能实战全集 , 我学习完了之后, 我给 老师在课上说的话做了个笔记,以及视频的内容,还有代码敲了一遍,然后添加了一些注释,把执行结果也整理 ...
- java 百万数据查询_java一次性查询几十万,几百万数据解决办法
java查询一次性查询几十万,几百万数据解决办法 很早的时候写工具用的一个办法. 当时是用来把百万数据打包 成rar文件. 所以用了个笨办法. 希望高手指导一下,有什么好方法没有啊 1.先批量查出所有 ...
- java 百万数据查询_JAVA技巧:Java中的大量数据查询
解决方案一:直接使用ResultSet来处理 从ResultSet中将查询结果读入collection,缓存在HttpSession或有状态bean中,翻页的时候从缓存中取出一页数据显示.这种方法有两 ...
- Java将mysql输出csv_使用Java将大量数据从数据库导出到.csv时出...
我,谢谢您的关注. 我想使用Java将大量数据,实际上是大量数据(600万行)导出到.csv文件.该应用程序是使用toplink(ojdbc14)的JPA摆动应用程序. 我尝试使用: 但是Buffer ...
最新文章
- 十二、进程的同步与互斥
- C# 调用python
- Android NFC开发详细总结
- Windows Azure Web Site (17) 设置Web App TimeOut时间
- Lesson 3 Part 1 Locally weighted regression
- 游戏中出现服务器维护中怎么办,游戏服务器显示维护中
- 电能表软件测试用例,一种用于电能表软件自动测试的方法专利_专利查询 - 天眼查...
- C++对二进制文件的操作实例
- 如何减小电压跟随器输出电阻_电压跟随器秘笈:LM358电压跟随器+运放问题
- 2-10配置Linux网络
- 全系列三极管应用参数和代换大全
- 如何用手机在图片上标箭头_如何在手机上快速给图片做标记?
- Type -C 耳机
- i7运行linux虚拟机会卡吗,i7 7200 linux 虚拟机
- uniapp 二维码展示和扫码
- 忽略链路状态的功能详解——网络测试仪实操
- Linux 系统基础 — 用户和组(吐血总结,超详细,看这一篇就够了!dog)
- python程序设计搜题软件_智慧职教APPPython程序设计答案搜题公众号
- Android学习之AlarmManager使用
- 【NLP】Praat库(2) Batch processing of files
热门文章
- 服务器被黑 追寻ip_网站服务器被攻击了如何查找木马(webshell)IP 篡改的痕迹...
- Deployer php自动部署,基于 deployer 的 Web 端自动部署
- 对于企业是云服务器划算还是自购服务器划算?
- 联阿里接腾讯,B站如何实现“意义非凡”的一年
- Adobe国际认证设计师含金量,能否代表设计师的真实水平?
- 京东“百亿补贴”提前20小时上线,电商价格战开打; iPhone 15 Pro玻璃面板泄露;凹语言 0.5.0发布|极客头条
- 天钰原装FP6606ACAP6芯片,仅5V至20V VBUS电源,过电压保护
- 前端vue-高德地图操作
- java高并发系列 - 第1天:必须知道的几个概念
- 阈的粤语发音_粤语发音规则完整版