- 浏览: 606798 次
- 性别:
- 来自: 郑州
文章分类
最新评论
-
AlanKay:
Mart_dai 写道Hi 齐晓威_518,我想问问,在exc ...
java 后台 Excel 文件生成后转化为字节流 -
18335864773:
国内的pageoffice插件也可以生成excel。也可以用流 ...
java 后台 Excel 文件生成后转化为字节流 -
JAVA_CLASSm:
你好,请问这个还有源码吗?我刚开始接触这个,想要源码学习一下. ...
同一账号不能多地登录(限制同一账号同一时刻只能一个用户登录使用,向QQ一样) -
pangjinquan:
...
前台JS获取后台的Json数据, 动态创建table并填充数据--转自一位朋友 -
lvjun106:
这是增加删除列,,,,
JQuery自动为表格增加一列
一年前写过一个百万级别数据库数据生成配置xml文件的程序,程序目的是用来把数据库里面的数据生成xml文件.程序可以配置多少文件生成到一个文件中去.
程序刚开始设计的时候说的是最多百万级别数据,最多50W数据生成到一个xml文件里面去,所以在做测试的时候自己也只是造了100W的数据并没有做过多数据量的测试,然后问题就来了....由于程序使用的局点数据量巨大,需要生成xml文件的客户资料接近千万级别的程度,而现场对程序的配置大约是100W条数据生成一个xml文件里面去,程序在这样的大数据量下面偶尔会有崩溃.
最近几天现场催的比较紧,最近抽空把这个问题处理了一下,在解决问题的过程中我把解决的步骤和方法记录了下来,正好和大家共享一下
现场提的问题概况:
数据量:生成xml,每个文件100W+ 条的数据
内存控制:最好不要超过512M
问题详情:在处理70W左右的时候内存溢出
一、先来看一下程序要生成的xml文件的结构
复制代码
<File>
<FileType>1</FileType>
<RType>12</RType>
<Version>03</Version>
<BNo>004</BNo>
<FileQ>5</FileQ>
<FNo>0006</FNo>
<RecordNum>1000000</RecordNum>
<!-- 上面是文件头 下面是百万个<RecordList> -->
<RecordList>
<Msisdn>10350719507</Msisdn>
<State>1</State>
<StartDate>20110303</StartDate>
<Date>20110419</Date>
<Balance>45000</Balance>
</RecordList>
... <!-- 可能百万个 <RecordList> 块-->
</File>
复制代码
二、给大家说一下如何把大数据生成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();
...
}
...
}
复制代码
如果碰到和我一样的需要给大家一个提醒.
oracle在每次执行executeBatch();进行批处理的时候,当前connection对应的rownum会根据操作的结果发生变化.
在执行pst.executeBatch(); 之后,当前连接的 rownum 数就会发生变化. 因此凡是通过rownum查询数据的程序都要小心这一点
下一篇将整理写java大数据(千万级别以上的)处理,包括 ftp大数据处理、文件生成大数据处理、数据库转移大数据处理、文件读取大数据处理等等.
<千万级别数据生成xml文件> by dyllove98 @ http://www.cnblogs.com/dyllove98
转载请表明出处。
程序刚开始设计的时候说的是最多百万级别数据,最多50W数据生成到一个xml文件里面去,所以在做测试的时候自己也只是造了100W的数据并没有做过多数据量的测试,然后问题就来了....由于程序使用的局点数据量巨大,需要生成xml文件的客户资料接近千万级别的程度,而现场对程序的配置大约是100W条数据生成一个xml文件里面去,程序在这样的大数据量下面偶尔会有崩溃.
最近几天现场催的比较紧,最近抽空把这个问题处理了一下,在解决问题的过程中我把解决的步骤和方法记录了下来,正好和大家共享一下
现场提的问题概况:
数据量:生成xml,每个文件100W+ 条的数据
内存控制:最好不要超过512M
问题详情:在处理70W左右的时候内存溢出
一、先来看一下程序要生成的xml文件的结构
复制代码
<File>
<FileType>1</FileType>
<RType>12</RType>
<Version>03</Version>
<BNo>004</BNo>
<FileQ>5</FileQ>
<FNo>0006</FNo>
<RecordNum>1000000</RecordNum>
<!-- 上面是文件头 下面是百万个<RecordList> -->
<RecordList>
<Msisdn>10350719507</Msisdn>
<State>1</State>
<StartDate>20110303</StartDate>
<Date>20110419</Date>
<Balance>45000</Balance>
</RecordList>
... <!-- 可能百万个 <RecordList> 块-->
</File>
复制代码
二、给大家说一下如何把大数据生成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();
...
}
...
}
复制代码
如果碰到和我一样的需要给大家一个提醒.
oracle在每次执行executeBatch();进行批处理的时候,当前connection对应的rownum会根据操作的结果发生变化.
在执行pst.executeBatch(); 之后,当前连接的 rownum 数就会发生变化. 因此凡是通过rownum查询数据的程序都要小心这一点
下一篇将整理写java大数据(千万级别以上的)处理,包括 ftp大数据处理、文件生成大数据处理、数据库转移大数据处理、文件读取大数据处理等等.
<千万级别数据生成xml文件> by dyllove98 @ http://www.cnblogs.com/dyllove98
转载请表明出处。
发表评论
-
webservice大文件传输
2015-02-28 11:03 1619来自: http://blog.sina.com.cn/s/b ... -
使用xmlhttp.send()方法的参数来传递大容量的数据
2015-02-28 10:13 810使用xmlhttp.send()方法的参数来传递大容量的数据 ... -
项目管理总结
2015-02-25 11:09 946【一】开发环境和测试 ... -
因为无能为力,所以顺其自然。因为心无所恃,所以随遇而安
2014-10-19 16:12 719在很久以前,有一个寺院,里面住着一老一小两位和尚。 有一天 ... -
从程序员到项目经理-转
2014-09-23 21:17 1406从薪水上看,当然是资 ... -
何为30而立?如何把握好成功的方向,才能驾驶自己的人生
2014-02-15 17:47 883你所有不曾料想过的问题,都会随着时间的推移而与你不期而遇;你所 ... -
你平静的生活或许会在某个不可预见的时刻被彻底打碎
2014-03-02 16:50 821故事一:年轻人被闹钟叫醒了,飞速地穿戴,洗漱,用早点,是的他今 ... -
网址-技术网站-jquery
2014-04-09 21:43 650技术网站-jquery http://site518.n ... -
ITCYC中一位同行发表的电子书,收藏下来方便下载观看
2014-03-18 23:19 712ITCYC中一位同行发表的电子书,收藏下来方便下载观看 ... -
原创: 莫叹人间苦与乐,天下何处无净境
2013-10-27 14:02 727莫叹人间苦与乐,天下何处无净境 试问阅者,你 ... -
评名言:大象无形,至刚易折
2013-10-27 13:59 930大象无形,至刚易折 古人云:大象的力量和体形甚 ... -
你会在公司工作多久?
2013-09-28 12:17 14561.介绍你自己 这个问题 ... -
感悟,是该换工作的时候了
2013-09-18 19:52 770一个人最大的价值不是创造了什么,而是给予了什么,生命如何短暂也 ... -
驾考科目三考试技巧
2013-09-17 17:19 807拐弯要减速减档,打转弯灯和鸣笛,不允许挂空挡。 直线或 ... -
亲爱的大叔
2013-09-01 21:23 1159要不是当初匆忙的脚步 迷途的我早已经放弃追逐 人生有太多反复难 ... -
21世纪将淘汰的八种人
2013-07-28 21:39 1027第一种被淘汰的人是“ ... -
合作法则
2013-07-28 21:34 7631、不与私欲太重的人合作,因为他们看不见别人的付出,只在意自己 ... -
品万像,会生活
2013-05-25 15:44 784不同的选择有不同的命运 ... -
蓦然回首--发现自己已不再青春年少
2013-01-16 22:44 1602岁月如流,年华似水,蓦然回首发现自己依然在原地,镜中的自己 ... -
系统 开始——运行——命令集锦
2012-11-29 09:16 878winver---------检查Windows版本 wmi ...
相关推荐
程序刚开始设计的时候说的是最多百万级别数据,最多50W数据生成到一个xml文件里面去,所以在做测试的时候自己也只是造了100W的数据并没有做过多数据量的测试,然后问题就来了....由于程序使用的局点数据量巨大,需要...
数字证书:从文件中读取数字证书,生成文件输入流,输入文件为c:/mycert.cer,获取一个处理X.509证书的证书工厂…… Java+ajax写的登录实例 1个目标文件 内容索引:Java源码,初学实例,ajax,登录 一个Java+ajax写...
数字证书:从文件中读取数字证书,生成文件输入流,输入文件为c:/mycert.cer,获取一个处理X.509证书的证书工厂…… Java+ajax写的登录实例 1个目标文件 内容索引:Java源码,初学实例,ajax,登录 一个Java+ajax写...
第2章 程序最优化.... 14 2.1 空间与时间... 14 2.1.1 空间与时间的概念和度量... 14 2.1.2 空间与时间的背反... 15 2.1.3 以空间换时间... 15 2.2 字典、哈希与Map. 19 2.2.1 字典的定义... 19 2.2.2 哈希表与哈希...
1、前端优化:活动开始前生成静态商品页面推送缓存和CDN,静态文件(JS/CSS)请求推送至文件服务器和CDN。 2、网络优化:如果是全国用户,最好是BGP多线机房,减少网络延迟。 3、应用服务优化:Nginx最佳配置、Tomcat...
2. RepositoryService:Activiti中每一个不同版本的业务流程的定义都需要使用一些定义文件,部署文件和支持数据(例如BPMN2.0 XML文件,表单定义文件,流程定义图像文件等),这些文件都存储在Activiti内建的...
所以很少存在简单重复的工作,加上Java 代码的精炼性和面向对象纯洁性(设计模式是 java 的灵魂),编程工作将变成一个让你时刻 体验创造快感的激动人心的过程. 为能和大家能共同探讨"设计模式",我将自己在学习中的心得...
1、前端优化:活动开始前生成静态商品页面推送缓存和CDN,静态文件(JS/CSS)请求推送至文件服务器和CDN。 2、网络优化:如果是全国用户,最好是BGP多线机房,减少网络延迟。 3、应用服务优化:Nginx最佳配置、Tomcat...
1、前端优化:活动开始前生成静态商品页面推送缓存和CDN,静态文件(JS/CSS)请求推送至文件服务器和CDN。 2、网络优化:如果是全国用户,最好是BGP多线机房,减少网络延迟。 3、应用服务优化:Nginx最佳配置、Tomcat...