java千万级别数据生成文件思路和优化

合集下载

Java中代码优化的几种方法

Java中代码优化的几种方法

Java中代码优化的几种方法Java中代码优化是提高程序性能和效率的关键。

在开发过程中,大部分程序员都会遇到性能瓶颈或效率低下的情况。

为了解决这些问题,我们需要对代码进行优化。

第一种方法是使用合适的数据结构。

在Java中,数据结构的选择直接影响程序的性能。

比如,使用ArrayList代替LinkedList可以提高随机访问元素的效率,而使用HashMap代替TreeMap可以提高插入和查找的效率。

第二种方法是避免重复计算。

在一些场景中,我们可能会多次计算相同的值。

为了提高效率,我们可以使用缓存技术,将计算结果缓存起来,下次需要的时候直接使用。

这样可以减少计算的次数,提高程序的性能。

第三种方法是减少对象的创建。

在Java中,对象的创建和销毁是比较耗时的操作。

为了提高程序的效率,我们可以尽量减少对象的创建次数。

比如,可以使用对象池来重复利用对象,避免频繁的创建和销毁。

第四种方法是使用适当的算法和数据结构。

在某些情况下,算法的选择直接影响程序的性能。

我们可以使用时间复杂度较低的算法,并选择合适的数据结构来提高程序的效率。

比如,使用快速排序而不是冒泡排序,可以大大提高排序的效率。

第五种方法是使用合适的编程技巧。

在编写代码时,我们可以使用一些常用的编程技巧来提高程序的性能。

比如,使用位运算来替代乘法和除法可以提高计算的效率,使用按位与运算来判断奇偶数可以提高程序的执行速度。

总结起来,Java中代码优化可以通过使用合适的数据结构、避免重复计算、减少对象的创建、使用适当的算法和数据结构,以及使用合适的编程技巧来实现。

通过优化代码,我们可以提高程序的性能和效率,提升用户体验。

在实际开发中,我们需要根据具体情况选择合适的优化方法,以达到最佳的效果。

java执行10000数据量计算优化

java执行10000数据量计算优化

java执行10000数据量计算优化
1.尽量使用单例。

2.合理使用静态变量,常用才使用,减少使用。

3.多使用final,如setter。

4.尽量不要在循环中创建对象(使用基本数据类型或者数组来代替),不要过多创建对象,不要在循环中使用try/catch。

5.尽量使用局部变量,局部变量存在栈中,比存在堆中的变量实例等速度都要快(但是规范要求尽量不要有局部变量,适当就行)。

6.操作局部变量要比读取全局变量要更快。

7.基本类型和包装类型一样,基本数据类型在栈中,包装类型在堆中,合理使用吧,能用基本类型就用基本类型,不行就用包装类型。

8.synchronized尽量不用,用的话范围尽量小。

9.尽量不要使用finalize。

10.合理使用给出最佳大小,尽量避免扩容,其他类似
11.尽量减少重复计算,如list.size在循环中可以提前算好,然后再在循环中使用13.尽量减少不必要的对象创建。

12.资源要及时关闭。

13.尽量使用位运算来代替逻辑运算,在条件判断中尽量用boolean。

14.尽早释放无用对象引用。

15.用一维数组代替二维数组。

16.尽量避免使用split,如果要用,可以使用的split(string,char),频繁的split可以缓存结果。

Mysql千万级别数据优化方案总结

Mysql千万级别数据优化方案总结

Mysql千万级别数据优化方案目录目录 (1)一、目的与意义 (1)1) 说明 (1)二、解决思路与根据(本测试表中数据在千万级别) (2)1) 建立索引 (2)2) 数据体现(主键非索引,实际测试结果其中fid建立索引) (2)3) MySQL分页原理 (2)4) 经过实际测试当对表所有列查询时 (3)三、总结 (3)1) 获得分页数据 (3)2) 获得总页数:创建表记录大数据表中总数通过触发器来维护 (3)一、目的与意义1)说明在MySql单表中数据达到千万级别时数据的分页查询结果时间过长,对此进行优达到最优效果,也就是时间最短;(此统计利用的jdbc连接,其中fid为该表的主键;)二、解决思路与根据(本测试表中数据在千万级别)1)建立索引优点:当表中有大量记录时,若要对表进行查询,第一种搜索信息方式是全表搜索,是将所有记录一一取出,和查询条件进行一一对比,然后返回满足条件的记录,这样做会消耗大量数据库系统时间,并造成大量磁盘I/O操作;第二种就是在表中建立索引,然后在索引中找到符合查询条件的索引值,最后通过保存在索引中的ROWID(相当于页码)快速找到表中对应的记录。

缺点:当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度。

2)数据体现(主键非索引,实际测试结果其中fid建立索引)未创建索引:SELECT fid from t_history_data LIMIT 8000000,10 结果:13.396s创建索引:SELECT fid from t_history_data LIMIT 8000000,10 结果:2.896sselect * from t_history_data where fid in ( 任意十条数据的id ) 结果:0.141s首先通过分页得到分页的数据的ID,将ID拼接成字符串利用SQL语句select * from table where ID in (ID字符串)此语句受数据量大小的影响比较小(如上测试);3)MySQL分页原理MySQL的limit工作原理就是先读取n条记录,然后抛弃前n条,读m条想要的,所以n越大,性能会越差。

Java实现大批量数据导入导出(100W以上) -(二)导出

Java实现大批量数据导入导出(100W以上) -(二)导出

Java实现⼤批量数据导⼊导出(100W以上) -(⼆)导出使⽤POI或JXLS导出⼤数据量(百万级)Excel报表常常⾯临两个问题:1. 服务器内存溢出;2. ⼀次从数据库查询出这么⼤数据,查询缓慢。

当然也可以分页查询出数据,分别⽣成多个Excel打包下载,但这种⽣成还是很缓慢。

⼤数据量导⼊请参考:那么如何解决呢?我们可以借助XML格式利⽤模板替换,分页查询出数据从磁盘写⼊XML,最终会以Excel多sheet形式⽣成。

亲测2400万⾏数据,⽣成Excel⽂件4.5G,总耗时1.5分钟。

我利⽤StringTemplate模板解析技术对XML模板进⾏填充。

当然也可以使⽤FreeMarker, Velocity等Java模板技术实现。

⾸先引⼊StringTemplate所需Jar包:使⽤技术为 stringTemplatepom.xml:1 <dependency>2<groupId>antlr</groupId>3<artifactId>antlr</artifactId>4<version>2.7.7</version>5</dependency>67<dependency>8<groupId>org.antlr</groupId>9<artifactId>stringtemplate</artifactId>10<version>3.2.1</version>11</dependency>⾸先准备导出Excel模板,然后打开-》另存为-》选择格式为XML,然后⽤⽂本打开XML,提取XML头模板(head.st可通⽤),数据体模板(boday.st):head.st可通⽤:1<?xml version="1.0"?>2<?mso-application progid="Excel.Sheet"?>3<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"4 xmlns:o="urn:schemas-microsoft-com:office:office"5 xmlns:x="urn:schemas-microsoft-com:office:excel"6 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"7 xmlns:html="/TR/REC-html40">8<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">9<Created>1996-12-17T01:32:42Z</Created>10<LastSaved>2013-08-02T09:21:24Z</LastSaved>11<Version>11.9999</Version>12</DocumentProperties>13<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">14<RemovePersonalInformation/>15</OfficeDocumentSettings>16<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">17<WindowHeight>4530</WindowHeight>18<WindowWidth>8505</WindowWidth>19<WindowTopX>480</WindowTopX>20<WindowTopY>120</WindowTopY>21<AcceptLabelsInFormulas/>22<ProtectStructure>False</ProtectStructure>23<ProtectWindows>False</ProtectWindows>24</ExcelWorkbook>25<Styles>26<Style ss:ID="Default" ss:Name="Normal">27<Alignment ss:Vertical="Bottom"/>28<Borders/>29<Font ss:FontName="宋体" x:CharSet="134" ss:Size="12"/>30<Interior/>31<NumberFormat/>32<Protection/>33</Style>34</Styles>boday.st:1 $worksheet:{2<Worksheet ss:Name="$it.sheet$">3<Table ss:ExpandedColumnCount="$it.columnNum$" ss:ExpandedRowCount="$it.rowNum$" x:FullColumns="1"4 x:FullRows="1" ss:DefaultColumnWidth="54" ss:DefaultRowHeight="14.25">5 $it.rows:{6<Row>7<Cell><Data ss:Type="String">$1$</Data></Cell>8<Cell><Data ss:Type="String">$2$</Data></Cell>9<Cell><Data ss:Type="String">$3$</Data></Cell>10</Row>11 }$12</Table>13</Worksheet>14 }$⽣成⼤数据量Excel类:ExcelGenerator:1package test.exportexcel;23import org.antlr.stringtemplate.StringTemplate;4import org.antlr.stringtemplate.StringTemplateGroup;5import test.exportexcel.bean.Row;6import test.exportexcel.bean.Worksheet;78import java.io.*;9import java.util.ArrayList;10import java.util.List;11import java.util.Random;1213/**14 * 类功能描述:generator big data Excel15 *16 * @author WangXueXing create at 19-4-13 下午10:2317 * @version 1.0.018*/19public class ExcelGenerator {20public static void main(String[] args) throws FileNotFoundException{21 ExcelGenerator template = new ExcelGenerator();22 template.output2();23 }2425/**26 * ⽣成数据量⼤的时候,该⽅法会出现内存溢出27 * @throws FileNotFoundException28*/29public void output1() throws FileNotFoundException{30 StringTemplateGroup stGroup = new StringTemplateGroup("stringTemplate");31 StringTemplate st4 = stGroup.getInstanceOf("test/exportexcel/template/test");32 List<Worksheet> worksheets = new ArrayList<>();3334 File file = new File("/home/barry/data/output.xls");35 PrintWriter writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream(file)));3637for(int i=0;i<30;i++){38 Worksheet worksheet = new Worksheet();39 worksheet.setSheet("第"+(i+1)+"页");40 List<Row> rows = new ArrayList<>();41for(int j=0;j<6000;j++){42 Row row = new Row();43 row.setName1("zhangzehao");44 row.setName2(""+j);45 row.setName3(i+" "+j);46 rows.add(row);47 }48 worksheet.setRows(rows);49 worksheets.add(worksheet);50 }5152 st4.setAttribute("worksheets", worksheets);53 writer.write(st4.toString());54 writer.flush();55 writer.close();56 System.out.println("⽣成excel完成");57 }5859/**60 * 该⽅法不管⽣成多⼤的数据量,都不会出现内存溢出,只是时间的长短61 * 经测试,⽣成2400万数据,2分钟内,4.5G⼤的⽂件,打开⼤⽂件就看内存是否⾜够⼤了62 * 数据量⼩的时候,推荐⽤JXLS的模板技术⽣成excel⽂件,谁⽤谁知道,⼤数据量可以结合该⽅法使⽤63 * @throws FileNotFoundException64*/65public void output2() throws FileNotFoundException{66long startTimne = System.currentTimeMillis();67 StringTemplateGroup stGroup = new StringTemplateGroup("stringTemplate");6869//写⼊excel⽂件头部信息70 StringTemplate head = stGroup.getInstanceOf("test/exportexcel/template/head");71 File file = new File("/home/barry/data/output.xls");72 PrintWriter writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream(file)));73 writer.print(head.toString());74 writer.flush();7576int sheets = 400;77//excel单表最⼤⾏数是6553578int maxRowNum = 60000;7980//写⼊excel⽂件数据信息81for(int i=0;i<sheets;i++){82 StringTemplate body = stGroup.getInstanceOf("test/exportexcel/template/body");83 Worksheet worksheet = new Worksheet();84 worksheet.setSheet(" "+(i+1)+" ");85 worksheet.setColumnNum(3);86 worksheet.setRowNum(maxRowNum);87 List<Row> rows = new ArrayList<>();88for(int j=0;j<maxRowNum;j++){89 Row row = new Row();90 row.setName1(""+new Random().nextInt(100000));91 row.setName2(""+j);92 row.setName3(i+""+j);93 rows.add(row);94 }95 worksheet.setRows(rows);96 body.setAttribute("worksheet", worksheet);97 writer.print(body.toString());98 writer.flush();99 rows.clear();100 rows = null;101 worksheet = null;102 body = null;103 Runtime.getRuntime().gc();104 System.out.println("正在⽣成excel⽂件的 sheet"+(i+1));105 }106107//写⼊excel⽂件尾部108 writer.print("</Workbook>");109 writer.flush();110 writer.close();111 System.out.println("⽣成excel⽂件完成");112long endTime = System.currentTimeMillis();113 System.out.println("⽤时="+((endTime-startTimne)/1000)+"秒");114 }115 }定义JavaBean:WorkSheet.java:1package test.exportexcel.bean;23import java.util.List;45/**6 * 类功能描述:Excel sheet Bean7 *8 * @author WangXueXing create at 19-4-13 下午10:219 * @version 1.0.010*/11public class Worksheet {12private String sheet;13private int columnNum;14private int rowNum;15private List<Row> rows;1617public String getSheet() {18return sheet;19 }20public void setSheet(String sheet) {21this.sheet = sheet;22 }2324public List<Row> getRows() {25return rows;26 }27public void setRows(List<Row> rows) {28this.rows = rows;29 }3031public int getColumnNum() {32return columnNum;33 }34public void setColumnNum(int columnNum) {35this.columnNum = columnNum;36 }3738public int getRowNum() {39return rowNum;40 }41public void setRowNum(int rowNum) {42this.rowNum = rowNum;43 }44 }Row.java:1package test.exportexcel.bean;23/**4 * 类功能描述:Excel row bean5 *6 * @author WangXueXing create at 19-4-13 下午10:227 * @version 1.0.08*/9public class Row {10private String name1;11private String name2;12private String name3;1314public String getName1() {15return name1;16 }17public void setName1(String name1) {1 = name1;19 }2021public String getName2() {22return name2;23 }24public void setName2(String name2) {2 = name2;26 }2728public String getName3() {29return name3;30 }31public void setName3(String name3) {3 = name3;33 }34 }另附实现源码: 此外,⼤数据量并并且Excel列较多时,会出现内存溢出。

Java中的性能优化与调优

Java中的性能优化与调优

Java中的性能优化与调优在现代软件开发中,性能优化和调优是非常重要的环节。

尤其是在Java开发中,由于其跨平台性和高度可扩展性,优化Java程序的性能成为了一个至关重要的任务。

本文将探讨一些常见的Java性能优化和调优技巧。

一、代码优化1. 减少方法调用:频繁的方法调用会带来性能损耗。

可以通过合并一些简单方法,避免不必要的调用,或者使用内联技术来减少方法调用次数。

2. 使用高效的数据结构与算法:选择合适的数据结构和算法可以显著提高代码的执行效率。

例如,使用HashMap而不是ArrayList来存储大量数据,或者使用二分查找而不是线性搜索。

3. 避免无谓的对象创建:频繁创建和销毁对象会导致垃圾回收器的频繁触发,影响程序性能。

可以使用对象池或者重用对象的方式来减少内存分配和垃圾回收开销。

4. 使用位运算代替乘除法:位运算在性能上比乘除法更高效。

例如,将乘法操作替换为位移运算可以提高代码的执行速度。

二、内存优化1. 减少内存占用:尽量避免占用过多的内存,可以通过控制对象的生命周期,释放无用的对象,以及压缩数据等方式来减少内存占用。

2. 使用缓存:将频繁使用的数据缓存起来,避免频繁的IO操作或计算,以提高程序的响应速度。

例如,可以使用缓存库或者手动实现缓存机制。

3. 注意资源的关闭:及时关闭打开的资源,如文件、数据库连接等,以释放占用的系统资源。

避免资源泄漏可能造成的性能问题。

三、多线程优化1. 合理使用线程池:线程池能够管理线程的创建和销毁,避免频繁创建和销毁线程的开销。

合理配置线程池的大小和工作队列的容量,以满足程序的并发需求。

2. 使用线程安全的数据结构:在多线程环境下,使用线程安全的数据结构可以避免数据竞争和线程冲突的问题。

例如,可以使用ConcurrentHashMap替代HashMap来确保线程安全性。

3. 避免过多的线程同步:过多的线程同步会带来性能的下降。

可以通过减少锁的粒度、使用无锁数据结构或CAS操作来减少线程同步的开销。

Java开发中的代码优化技巧

Java开发中的代码优化技巧

Java开发中的代码优化技巧Java作为一种广泛应用的编程语言,其开发中的代码优化技巧也越来越受到开发者们的关注。

优化代码可以帮助提高程序的运行效率、减少资源占用、降低出现bug的风险等。

本文将结合实例和理论,介绍Java开发中的代码优化技巧。

一、使用合适的数据结构在Java开发中,选择合适的数据结构可以帮助我们更快地完成开发任务。

例如,在需要存储大量数据时,我们可以选择使用HashMap而非List,因为HashMap的查找效率更高。

同时,Java中还有一些专门优化某些场景的数据结构,例如ConcurrentHashMap、CopyOnWriteArrayList等等,这些数据结构可以帮助我们更好地应对高并发场景或者需要频繁遍历的场景。

二、避免使用字符串拼接在Java中,字符串的拼接通常会使用“+”符号来实现,例如:String name = "John";String age = "26";String info = "我的名字是" + name + ",今年" + age + "岁。

";这样写的代码虽然功能正常,但是在性能上会受到很大的影响,因为每次拼接字符串时都会创建一个新的String对象,导致不必要的内存开销。

因此,我们可以使用StringBuilder或StringBuffer来替代字符串拼接操作,因为它们是可变的字符序列,可以更加高效地拼接字符串。

三、减少对象的创建在Java中,对象的创建是比较消耗资源的一项操作,因此我们需要尽量减少对象的创建次数。

例如,创建一个ArrayList对象时,我们应该在声明时就确定其初始容量,避免在添加元素时重复扩容。

同时,在一些简单的计算过程中,我们也可以考虑使用基本类型,避免不必要的装箱操作。

例如,int比Integer更加高效,因为int不需要进行装箱拆箱的操作。

Java:导出Excel大批量数据的优化过程

Java:导出Excel⼤批量数据的优化过程背景团队⽬前在做⼀个⽤户数据看板(下⾯简称看板),基本覆盖⽤户的所有⾏为数据,并⽣成分析报表,⽤户⾏为由多个数据来源组成(餐饮、⽣活⽇⽤、充值消费、交通出⾏、通讯物流、交通出⾏、医疗保健、住房物业、运动健康...),基于⼤量数据的组合、排序和统计。

根据最新的统计报告,每天将近100W+的⾏为数据产⽣,所以这个数据基数是⾮常⼤的。

⽽这个数据中⼼,对接很多的业务团队,这些团队根据⾃⼰的需要,对某些维度进⾏筛选,然后直接从我们的中⼼上下载数据(excel)⽂档进⾏分析。

所以下个⼏⼗万上百万⾏的数据是很常见的。

问题和解决⽅案遇到的问题⽬前遇到的主要问题是,随着⾏为能⼒逐渐的完善闭环,⽤户数据沉淀的也越来越多了,同时业务量的也在不断扩⼤。

业务团队有时候会下载超量的数据来进⾏分析,平台上的数据下载能⼒就显得尤为重要了。

⽽我们的问题是下载效率太慢,10W的数据⼤约要5分钟以上才能下载下来,这显然有问题了。

解决步骤代码是之前团队遗留的,原先功能没开放使⽤,没有数据量,所以没有发现问题。

以下是原来的导出模块,原程序如下,我做了基本还原。

现在如何保证数据的⾼效导出是我们最重要的⽬标,这个也是业务团队最关⼼的。

1/**2 * 获取导出的Excel的⽂件流信息3 * @param exportData4 * @return5 * @throws Exception6*/7private OutputStream getExportOutPutStream(List<UBehavDto> exportData) throws Exception {8 JSONObject object = new JSONObject();9 List<ExcelCell[]> excelCells = new ArrayList<>();10 String[] headers = new String[] { "A字段","B字段","C字段","D","E","F","G","H","I","J","K","L",11 "M","N","O","P","Q","R","S","T","U","V","W",12 "X","Y","Z","AA","AB","AC","AD","AE字段","AF字段","AG字段" };13 ExcelCell[] headerRow = getHeaderRow(headers);14 excelCells.add(headerRow);15 String pattern = "yyyy-MM-dd hh:mm:ss";16for (UBehavDto uBehavDto:exportData) {17 String[] singleRow = new String[] { uBehavDto.getA(),uBehavDto.getB(),uBehavDto.getC(),uBehavDto.getD(),uBehavDto.getE(),uBehavDto.getF(),18 DateFormatUtils.format(uBehavDto.getAddTime(), pattern),DateFormatUtils.format(uBehavDto.getDate(), pattern),19 uBehavDto.getG(),uBehavDto.getH(),uBehavDto.getI(),uBehavDto.getJ(),uBehavDto.getK(),uBehavDto.getL(),uBehavDto.getM(),20 uBehavDto.getN(),uBehavDto.getO(),uBehavDto.getP(),21 uBehavDto.getQ(),uBehavDto.getR(),uBehavDto.getS(),String.valueOf(uBehavDto.getT()),uBehavDto.getMemo(),uBehavDto.getU(),uBehavDto.getV(),22 uBehavDto.getW(),uBehavDto.getX(),23 uBehavDto.getY(),uBehavDto.getZ(),uBehavDto.getAA(),uBehavDto.getAB(),uBehavDto.getAC() };24 ExcelCell[] cells = new ExcelCell[singleRow.length];25 ExcelCell getA=new ExcelCell();getA.setValue(uBehavDto.getA());26 ExcelCell getB=new ExcelCell();getB.setValue(uBehavDto.getB());27 ExcelCell getC=new ExcelCell();getC.setValue(uBehavDto.getC());28 ExcelCell getD=new ExcelCell();getD.setValue(uBehavDto.getD());29 ExcelCell getE=new ExcelCell();getE.setValue(uBehavDto.getE());30 ExcelCell getF=new ExcelCell();getF.setValue(uBehavDto.getF());31 ExcelCell getAddTime=new ExcelCell();getAddTime.setValue(DateFormatUtils.format(uBehavDto.getAddTime(), pattern));32 ExcelCell getDate=new ExcelCell();getDate.setValue(DateFormatUtils.format(uBehavDto.getDate(), pattern));33 ExcelCell getG=new ExcelCell();getG.setValue(uBehavDto.getG());34 ExcelCell getH=new ExcelCell();getH.setValue(uBehavDto.getH());35 ExcelCell getI=new ExcelCell();getI.setValue(uBehavDto.getI());36 ExcelCell getJ=new ExcelCell();getJ.setValue(uBehavDto.getJ());37 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getK());38 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getL());39 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getM());40 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getN());41 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getO());42 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getP());43 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getQ());44 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getR());45 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getS());46 ExcelCell a=new ExcelCell();a.setValue(String.valueOf(uBehavDto.getT()));47 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getMemo());48 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getU());49 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getV());50 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getW());51 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getX());52 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getY());53 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getZ());54 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getAA());55 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getAB());56 ExcelCell a=new ExcelCell();a.setValue(uBehavDto.getAC());57 ExcelCell[] cells = {58new ExcelCell(uBehavDto.getA()),59new ExcelCell().setValue(uBehavDto.getB()),60new ExcelCell().setValue(uBehavDto.getC()),61new ExcelCell().setValue(uBehavDto.getD()),62new ExcelCell().setValue(uBehavDto.getE()),63new ExcelCell().setValue(uBehavDto.getF()),64new ExcelCell().setValue(DateFormatUtils.format(uBehavDto.getAddTime(), pattern)),65new ExcelCell().setValue(DateFormatUtils.format(uBehavDto.getDate(), pattern)),66new ExcelCell().setValue(uBehavDto.getG()),67new ExcelCell().setValue(uBehavDto.getH()),68new ExcelCell().setValue(uBehavDto.getI()),69new ExcelCell().setValue(uBehavDto.getJ()),70new ExcelCell().setValue(uBehavDto.getK()),71new ExcelCell().setValue(uBehavDto.getL()),72new ExcelCell().setValue(uBehavDto.getM()),73new ExcelCell().setValue(uBehavDto.getN()),74new ExcelCell().setValue(uBehavDto.getO()),75new ExcelCell().setValue(uBehavDto.getP()),76new ExcelCell().setValue(uBehavDto.getQ()),77new ExcelCell().setValue(uBehavDto.getR()),78new ExcelCell().setValue(uBehavDto.getS()),79new ExcelCell().setValue(String.valueOf(uBehavDto.getT())),80new ExcelCell().setValue(uBehavDto.getMemo()),81new ExcelCell().setValue(uBehavDto.getU()),82new ExcelCell().setValue(uBehavDto.getV()),83new ExcelCell().setValue(uBehavDto.getW()),84new ExcelCell().setValue(uBehavDto.getX()),85new ExcelCell().setValue(uBehavDto.getY()),86new ExcelCell().setValue(uBehavDto.getZ()),87new ExcelCell().setValue(uBehavDto.getAA()),88new ExcelCell().setValue(uBehavDto.getAB()),89new ExcelCell().setValue(uBehavDto.getAC())90 };9192for(int idx=0;idx<singleRow.length;idx++) {93 ExcelCell cell = new ExcelCell();94 cell.setValue(singleRow[idx]);95 cells[idx] = cell;96 }97 excelCells.add(cells);98 }99 object.put("⾏为数据", excelCells);100 ExcelUtils utils = new ExcelUtils();101 OutputStream outputStream = utils.writeExcel(object);102return outputStream;103 }看看标红的代码,这个⽣成Excel的⽅式是对Excel中的每⼀个cell进⾏渲染,逐⾏的进⾏数据填充,效率太慢了,根据⽇志分析发现:基本时间都耗费在数据⽣成Excel上。

记一次Java导出大批量Excel优化

记⼀次Java导出⼤批量Excel优化常⽤的excel导出⽅案,详情见,其中jxl、esayEscel 底层都是基于 poi,它们仅仅是对 poi 进⾏了封装,使导出 excel 的代码更加简洁(封装poi,导出 excel 的⼯具类有很多,jxl 和 esayExcel 使⽤的⽐较多)。

所以,如果遇到 excel 导出效率低下,直接基于 poi 导出 Excel,效率肯定是最⾼的,只是代码⽐较繁琐与杂乱。

我主要是基于 esayExcel (⽬前使⽤⽐较多),对其 api 进⾏衍⽣与应⽤,解决导出⼤量 Excel 导致的 OOM,或者数据超界异常:ng.IllegalArgumentException: Invalid row number (1048576) outside allowable range (0..1048575)应⽤是基于100W条数据进⾏的测试,数据的获取代码如下1package bean;23import com.alibaba.excel.annotation.ExcelProperty;4import com.alibaba.excel.annotation.format.DateTimeFormat;5import com.alibaba.excel.annotation.format.NumberFormat;6import lombok.Data;7import lombok.experimental.Accessors;89import java.util.Date;1011/**12 * @author dz13 * @date 2021-11-06 上午 9:1414*/15 @Accessors(chain = true)16 @Data17public class ExcelBean {1819 @ExcelProperty("主键id")20private String id;2122 @ExcelProperty("姓名")23private String name;2425 @ExcelProperty("地址")26private String address;2728 @ExcelProperty("年龄")29private Integer age;3031 @ExcelProperty("数量")32private Integer number;3334 @NumberFormat("#.##")35 @ExcelProperty("⾝⾼")36private Double high;3738 @ExcelProperty("距离")39private Double distance;4041 @DateTimeFormat("yyyy-MM-dd HH:mm:ss")42 @ExcelProperty("开始时间")43private Date startTime;4445 @ExcelProperty("结束时间")46private Date endTime;47 }1/**2 * 获取excel 导出的数据3 *4 * @return list 集合5*/6private List<ExcelBean> getDate() {7 ("开始⽣成数据");8 Date date = new Date();9long startTime = System.currentTimeMillis();10 List<ExcelBean> list = Lists.newArrayList();11for (int i = 0; i < 1000000; i++) {12 ExcelBean bean = new ExcelBean();13 bean.setId(UUID.randomUUID().toString()).14 setName("隔壁⽼樊" + i).15 setAddress("北京市朝阳区酒仙桥" + i + "路").16 setAge(i).17 setNumber(i + 10000).18 setHigh(1.234 * i).19 setDistance(1.234 * i).20 setStartTime(date).21 setEndTime(date);22 list.add(bean);23 }24 ("数据⽣成结束,数据量={},耗时={}ms", list.size(), System.currentTimeMillis() - startTime);25return list;26 }pom 依赖1<dependency>2<groupId>org.projectlombok</groupId>3<artifactId>lombok</artifactId>4</dependency>5<dependency>6<groupId>com.alibaba</groupId>7<artifactId>easyexcel</artifactId>8<version>2.2.10</version>9</dependency>依赖 esayexcel 时,如果项⽬已经依赖了 poi,有可能会产⽣jar 包依赖冲突(easyexcel底层也是基于 poi),解决⽅案如下:⽅案⼀:查看 easyexcel 中依赖的 poi 的版本,然后将项⽬其余地⽅的版本修改成该版本,使项⽬依赖的 poi 版本和 easyexcel 依赖的版本⼀致⽅案⼆:在 esayexcel 中将 poi 的依赖排除掉,如下<dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.2.10</version><exclusions><exclusion><groupId>org.apache.poi</groupId><artifactId>poi</artifactId></exclusion><exclusion><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId></exclusion><exclusion><groupId>org.apache.poi</groupId><artifactId>poi-ooxml-schemas</artifactId></exclusion></exclusions></dependency>常量的定义1public static final String FILE_NAME = "D:\\test_" + System.currentTimeMillis() + ".xlsx";2// 每个 sheet 写⼊的数据3public static final int NUM_PER_SHEET = 300000;4// 每次向 sheet 中写⼊的数据(分页写⼊)5public static final int NUM_BY_TIMES = 50000;1.EasyExcel 导出 excel 应⽤使⽤ esayExcel ⾃带的 api 导出 excel 的应⽤,代码如下1/**2 * ⽅法⼀:将数据写⼊到excel3 * 直接调⽤api,适合⼩数据量4 * 100W条数据33s5*/6 @Test7public void writeExcelByApi() {8 String fileName = FILE_NAME;9 ("导出excel名称={}", fileName);10long startTime = System.currentTimeMillis();11// 直接调⽤api12 List<ExcelBean> date = getDate();13 EasyExcel.write(fileName, ExcelBean.class).sheet().doWrite(date);14 ("导出excel结束,数据量={},耗时={}ms", date.size(), System.currentTimeMillis() - startTime);15 }当 list 对象数据量太多,就会产⽣异常:原因是单个 excel ⼀个 sheet 的最⼤数据量为 10485751 ng.IllegalArgumentException: Invalid row number (1048576) outside allowable range (0..1048575)23 at org.apache.poi.xssf.streaming.SXSSFSheet.createRow(SXSSFSheet.java:123)4 at org.apache.poi.xssf.streaming.SXSSFSheet.createRow(SXSSFSheet.java:65)5 at com.alibaba.excel.util.WorkBookUtil.createRow(WorkBookUtil.java:70)6 at com.alibaba.excel.write.executor.ExcelWriteAddExecutor.addOneRowOfDataToExcel(ExcelWriteAddExecutor.java:67)7 at com.alibaba.excel.write.executor.ExcelWriteAddExecutor.add(ExcelWriteAddExecutor.java:56)8 at com.alibaba.excel.write.ExcelBuilderImpl.addContent(ExcelBuilderImpl.java:58)9 at com.alibaba.excel.ExcelWriter.write(ExcelWriter.java:161)10 at com.alibaba.excel.ExcelWriter.write(ExcelWriter.java:146)11 at com.alibaba.excel.write.builder.ExcelWriterSheetBuilder.doWrite(ExcelWriterSheetBuilder.java:61)12 at mytest.TestExcel.writeExcelByApi(TestExcel.java:40)13 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)14 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)15 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)16 at ng.reflect.Method.invoke(Method.java:498)17 at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)18 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)19 at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)20 at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)21 at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)22 at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)23 at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)24 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)25 at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)26 at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)27 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)28 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)29 at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)30 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)31 at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)32 at org.junit.runners.ParentRunner.run(ParentRunner.java:413)33 at org.junit.runner.JUnitCore.run(JUnitCore.java:137)34 at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)35 at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)36 at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)37 at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)2.EasyExcel 导出 excel 应⽤优化⼀:execl 数据量超过1048575将数据写⼊到不同的 sheet,保证每个 sheet 的数据量⼩于 1048575 ⾏,解决此问题,代码如下1/**2 * ⽅法⼆:导出多个sheet3 * easyExcel 底层是 POI 实现的,POI 单个sheet 最多只能导出 1048576 ⾏,超过该⾏数,会产⽣如下异常4 * ng.IllegalArgumentException: Invalid row number (1048576) outside allowable range (0..1048575)5 * <p>6 * 11:57:55.541 [main] INFO mytest.TestExcel - 写⼊sheet=sheet0,数据量300000-0=300000,耗时=6055ms7 * 11:57:59.701 [main] INFO mytest.TestExcel - 写⼊sheet=sheet1,数据量600000-300000=300000,耗时=4159ms8 * 11:58:03.827 [main] INFO mytest.TestExcel - 写⼊sheet=sheet2,数据量900000-600000=300000,耗时=4126ms9 * 11:58:05.193 [main] INFO mytest.TestExcel - 写⼊sheet=sheet3,数据量1000000-900000=100000,耗时=1366ms10 * 11:58:17.418 [main] INFO mytest.TestExcel - 导出excel结束,总数据量=1000000,耗时=31297ms11*/12 @Test13public void writeExcelByMulSheet() {14 String fileName = FILE_NAME;15 ("导出excel名称={}", fileName);16long startTime = System.currentTimeMillis();17// 获取数据18 List<ExcelBean> date = getDate();19// 获取 sheet 的个数20int sheetNum = date.size() % NUM_PER_SHEET == 0 ? date.size() / NUM_PER_SHEET : date.size() / NUM_PER_SHEET + 1;21// 指定写⼊的⽂件22 ExcelWriter excelWriter = EasyExcel.write(fileName, ExcelBean.class).build();23for (int i = 0; i < sheetNum; i++) {24long l = System.currentTimeMillis();25// 设置 sheet 的名字(sheet不能相同)26 String sheetName = "sheet" + i;27 WriteSheet writeSheet = EasyExcel.writerSheet(i, sheetName).build();28int startNum = i * NUM_PER_SHEET;29int endNum = i == sheetNum - 1 ? date.size() : (i + 1) * NUM_PER_SHEET;30 excelWriter.write(date.subList(startNum, endNum), writeSheet);31 ("写⼊sheet={},数据量{}-{}={},耗时={}ms", sheetName, endNum, startNum, endNum - startNum, System.currentTimeMillis() - l);32 }33// 最好放在 finally中34 excelWriter.finish();35 ("导出excel结束,总数据量={},耗时={}ms", date.size(), System.currentTimeMillis() - startTime);36 }3.EasyExcel 导出 excel 应⽤优化⼆:数据源 list 太⼤,直接读取全部的 list 数据导致 OOM将 list 数据进⾏分页读取,并进⾏分页写⼊到 excel。

JAVA笔记-如何将百万级数据高效的导出到Excel表单

JAVA笔记-如何将百万级数据⾼效的导出到Excel表单 今天,⼀朋友问我使⽤JAVA有没有什么办法导出百万级的数据到Excel⼯作表。

当时我的第⼀个念头就是这真的是⼀个好疯狂的念头。

然后就想假如真的有这样类似的需求,我⾃⼰应该怎么做呢? ps: ⾸先科普⼀下基础知识 Excel 2003及以下的版本。

⼀张表最⼤⽀持65536⾏数据,256列。

也就是说excel2003完全不可能满⾜百万数据导出的需求。

Excel 2007-2010版本。

⼀张表最⼤⽀持1048576⾏,16384列; 笔者使⽤的是office 2010,更⾼的版本笔者没有使⽤过,暂时⽆法判断。

由此看来百万级的数据量对Excel⾃⾝已经是属于接近极限的程度。

假如我们有更⼤的需求怎么办呢? 既然单表⽀持最⼤是104w条数据,那么更⼤的需求量我们就只能通过程序级分表操作的⽅式来实现了。

O(∩_∩)O哈哈~ 对于操作Excel的类库。

笔者其实了解的并不是很多。

只是很早以前使⽤过POI这个类库,感觉很不错。

于是决定从它⼊⼿。

看看POI有没有什么⽐较有效的好点的解决办法。

由于笔者以前使⽤的POI版本⽐较低。

⽽且使⽤于excel 2003版本。

所以遇到了不少问题。

编辑器: Intellij IDEA 13.2 类库需求: POI-3.10-Final1<dependency>2<groupId>org.apache.poi</groupId>3<artifactId>poi</artifactId>4<version>3.10-FINAL</version>5</dependency> 新建⼀个Maven项⽬。

根据笔者以往的经验,直接使⽤POI写了⼀份代码。

执⾏的时候直接报错了。

1public static void Excel2003Operate(String filePath) throws Exception {2 HSSFWorkbook hssfWorkbook = new HSSFWorkbook(new FileInputStream(new File(filePath)));3 HSSFSheet sheet = hssfWorkbook.getSheetAt(0);4for (int i = 0; i < 10000; i++) {5 HSSFRow hssfRow = sheet.createRow(i);6for (int j = 0; j < 10; j++) {7 HSSFCellUtil.createCell(hssfRow, j, String.valueOf(Math.random()));8 }9 }10 FileOutputStream out = new FileOutputStream("workbook.xlsx");11 hssfWorkbook.write(out);12 out.close();13 }1 Connected to the target VM, address: '127.0.0.1:62382', transport: 'socket'2 Exception in thread "main" org.apache.poi.poifs.filesystem.OfficeXmlFileException: The supplied data appears to be in the Office 2007+ XML. You are calling the part of POI that deals with OLE2 Office Documents. You need to call a different3 at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:131)4 at org.apache.poi.poifs.storage.HeaderBlock.<init>(HeaderBlock.java:104)5 at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:128)6 at ermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:342)7 at ermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:323)8 at dev.tinyz.excel.POIUtil.Excel2003Operate(POIUtil.java:23)9 at dev.tinyz.excel.Main.main(Main.java:16)10 Disconnected from the target VM, address: '127.0.0.1:62382', transport: 'socket' 运⾏直接报错了。

如何在Java编程中做到快速迭代和持续优化

如何在Java编程中做到快速迭代和持续优化在当今快节奏的软件开发环境中,快速迭代和持续优化是取得成功的关键。

对于 Java 编程来说,更是如此。

下面就让我们一起来探讨如何在 Java 编程中实现这两个重要的目标。

要做到快速迭代和持续优化,首先得有清晰明确的目标和需求。

在项目开始之前,一定要深入理解业务需求,与相关人员充分沟通,确保对项目的目标有清晰的认识。

这就像是在旅行前知道自己的目的地一样,只有方向明确,才能选择合适的路线。

代码的质量是实现快速迭代和持续优化的基础。

保持代码的简洁性、可读性和可维护性至关重要。

避免过度复杂的设计和冗长的函数,遵循良好的编程规范和设计原则,比如单一职责原则、开闭原则等。

一个清晰易懂的代码结构能让开发者更容易理解和修改代码,从而提高迭代的速度。

测试驱动开发(TDD)是一种非常有效的方法。

先编写测试用例,然后再编写实现代码,确保代码在每次修改后都能通过所有的测试。

这样可以在早期发现代码中的问题,减少后期的返工和调试时间。

同时,自动化测试能够快速反馈代码的改动是否影响了原有功能,为快速迭代提供了保障。

合理地运用设计模式也能帮助我们在 Java 编程中更好地实现快速迭代和持续优化。

例如,使用观察者模式可以实现对象之间的解耦,当需求发生变化时,只需要修改相应的观察者或者被观察者,而不会影响到整个系统的结构。

在代码实现过程中,要注重代码的性能优化。

比如,对于频繁使用的对象,可以考虑使用对象池来减少对象创建和销毁的开销;在处理字符串连接时,使用 StringBuilder 而不是简单的字符串相加,以提高性能。

版本控制系统是不可或缺的工具。

Git 就是一个非常流行的版本控制系统。

通过它,我们可以方便地管理代码的版本,轻松回滚到之前的某个稳定版本,也可以比较不同版本之间的差异,快速定位问题所在。

团队的协作和沟通也是关键因素。

开发人员之间要及时交流,分享自己的想法和发现的问题。

定期的代码审查可以发现潜在的问题,提高代码质量,促进团队成员之间的知识共享和技术提升。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

一年前写过一个百万级别数据库数据生成配置xml文件的程序,程序目的是用来把数据库里面的数据生成xml文件.程序可以配置多少文件生成到一个文件中去.

程序刚开始设计的时候说的是最多百万级别数据,最多50W数

据生成到一个xml文件里面去,所以在做测试的时候自己也只是造了100W的数据并没有做过多数据量的测试,然后问题就来了....由于程序使用的局点数据量巨大,需要生成xml文件的客户资料接近千万级别的程度,而现场对程序的配置大约是100W条数据生成一个xml文件里面去,程序在这样的大数据量下面偶尔会有崩溃.

最近几天现场催的比较紧,最近抽空把这个问题处理了一下,

在解决问题的过程中我把解决的步骤和方法记录了下来,正好和大家共享一下

现场提的问题概况: 数据量:生成xml,每个文件100W+ 条的数据 内存控制:最好不要超过512M 问题详情:在处理70W左右的时候内存溢出

一、先来看一下程序要生成的xml文件的结构 1 12 03 004 5 0006 1000000 10350719507 1 20110303 20110419 45000 ...

二、给大家说一下如何把大数据生成xml文件

1、小数据量的情况下 < 1W条数据

比较好用的方法是使用开源框架,比如XStream 直接把

javabean 生成 xml

优点:api操作简单,方便维护

缺点:数据量大的情况下太消耗内存

2、大数据量生成一个xml文件(本程序采用的方法)

自己做的一个可以使用极少的内存生成无限制大的xml文件

框架由3部分生成xml文件

第一部分:生成文件头

例如: xxx.toXML(Object obj, String fileName)

第二部分:通过每次向文件里面追加3000(可配置)条数据

的形式生成文件块

例如:xxx.appendXML(Object object); //object 可以是ArrayList 或者一个单独的javaBean

第三部分:生成xml文件尾巴

例如:xxx.finishXML();

程序中的调用:调用xxx.toXML(Object obj, String

fileName) 生成文件头之后,可以循环从数据库中读取数据生成ArrayList,通过xxx.appendXML(Object object) 方法追加到xml文件里面,xxx.finishXML() 对文件进行收尾

对框架说明:我上面提供的例子有文件头 + 文件块 + 文件

尾巴. 如果和你们的实际使用文件不太一致的话,可以参考上面提供的思路修改一下即可,主要的方法是把相同的文件块部分分离出来通过追加的形式写入xml文件.

有了思路之后,大家可以尝试着自己写一个类似的大数据处理框架(千万级别以上),如何有什么需要帮助的可以直接联系我,因为是公司的程序,不太敢放出来,怕......

三、我是如何测试性能和优化的

1、手动排除

根据文件崩溃时候的日志发现是在生成xml的框架里

面报的错误,第一想到的是框架有些资源没有释放.于是把自己做的文件生成框架整体的排查了一遍,并且自己写个简单程序生成200万条数据,使用xml框架生成一个xml文件,整个生成过程中任务管理器(xp)查看程序对应的java进程使用的内存基本在20M左右,因此排除框架的问题.怀疑是数据库查询和调用框架的部门出现问题.

检测了一遍主程序的关键部分代码,优化了一下字符

串处理.手动的释放一些对象的内存(例如:调用ArrayList.clear(),或者把对象置空等),分配512内存后运行程序,60万数据的时候内存溢出,因为能主动释放的对象都已经释放掉了,还是没有解决,果断放弃看代码,准备使用JProfile进行内存检测.

2、手动排除没有解决,借助内存分析工具JProfile进行排

通过在数据库中生成300W条数据,在JProfile上面

多跑程序,一边运行,一边调用JProfile 提供的执行GC按钮主动运行垃圾回收,运行50W数据后,通过检测中发现 java.long.String[] 和 oracle.jdbc.driver.Binder[] 两个对象的数目一直保持在自增状态,而且数目基本上差不多,对象数目 都在200W以上,由于java.long.String[]对象是需要依赖对象而存在的,因此断定问题就出在oracle.jdbc.driver.Binder[]上面,由于改对象存在引用导致String[]不能正常回收.

3、通过在JProfile对象查看对象的管理

检测到oracle.jdbc.driver.Binder 被 oracle.jdbc.driver.T4CPreparedStatement 引起,而T4CPreparedStatement正好是Oracle对jdbc OraclePreparedStatement的具体实现,因此断定是在数据库处理方面出现的问题导致oracle.jdbc.driver.Binder对象不能正常释放,通过再一次有目的的检测代码,排查jdbc数据查询的问题,把问题的矛头直至数据库的批处理和事务处理.因此程序是每生成一个文件成功后,会把已经处理的数据转移到对应的历史表中进行备份,而再个表操作的过程中使用了批处理和事务,使用批处理主要是保证执行速度,使用事务主要是保证同时成功和失败。

4、又因此程序每次从数据库中查询3000条数据处理,所以

准备监控oracle.jdbc.driver.Binder的对象数目是否和查询次数对应.,通过在程序中Sysout输出查询次数 + JProfile运行GC测试 Binder,数据匹配,证实是java在数据库批处理的过程中有些问题.

5、专门把批处理代码提取出来通过JProfile内存分析.最终

问题定位完毕.

原因如下:100W数据生成一个文件的过程中,等文件

生成完毕之后才能把数据库中的数据备份到历史表中,这个时候才能进行事务的提交,也就是执行commit(), 并且删除原表数据,100W数据按照3000一批写入文件,每批次只是通过 PreparedStatement.addBatch();加入到批次里面去,并没有执行PreparedStatement.executeBatch(),而是在commit()之前统一调用的PreparedStatement.executeBatch(),这样的话PreparedStatement就会缓存100W条数据信息,造成了内存溢出.

错误的方法如下:

try{ conn.setAutoCommit(false); pst = conn.prepareStatement(insertSql); pstDel = conn.prepareStatement(delSql); pstUpdate = conn.prepareStatement(sql); ... //totalSize = 100W数据 / 3000一批次 for (int i = 1; i <= totalSize; i++) {

client.appendXML(list); } // 错误的使用方法 client.finishXML(); pst.executeBatch(); pstDel.executeBatch(); } ... finally { try { if (isError) { conn.rollback(); } else conn.commit(); ... } ... }

正确的方法如下 try{

conn.setAutoCommit(false); pst = conn.prepareStatement(insertSql); pstDel = conn.prepareStatement(delSql); pstUpdate = conn.prepareStatement(sql); ... //totalSize = 100W数据 / 3000一批次 for (int i = 1; i <= totalSize; i++) { list = 从数据库中查询3000条数据 client.appendXML(list);

pst.executeBatch(); pstDel.executeBatch(); } client.finishXML();

} ... finally { try { if (isError) { conn.rollback(); } else conn.commit(); ... }

相关文档
最新文档