关于遍历大数据量数据库内存溢出

superyjcqw123 2013-06-27 05:03:40
public void batchUpdate(){
//循环遍历所有INFOMATION_ARTICLE
Article article = new Article();
List<Article> batchList= new ArrayList<Article>();
String content=null;
List<Article> list= new ArrayList<Article>();
for(int i=0;i<700;i++){
article.setStartRow(i*1000);
article.setEndRow((i+1)*1000);
list = commonDao.queryForList("Article.getArticlePage", article);
for (Article art : list) {
content = art.getArticleContent();
int cou = 1;
List<Word> artWords = getWords(art.getId());
for (Word word : artWords) {
if (cou++ > 10) {
break;
}
try {
content=content.replace(word.getUrl(), word.getWordName());//去掉标签
content=content.replaceFirst(word.getWordName(), word.getUrl());//替换第一个
} catch (Exception e) {

}
}
Article a = new Article();
a.setId(art.getId());
a.setArticleContent(content);
batchList.add(a);
}
commonDao.batchUpdate("Article.update", batchList);
batchList.clear();
System.out.println(i);
}



1.上面一共有70w条数据,每行数据里存的是文章,所以数据比较大
2.每次遍历1000条去修改

为什么javaw.exe一直往上涨,遍历到1w的时候已经占1G内存了,请问代码哪里有问题,或者有什么好的建议?是gc回收的太慢了?
...全文
1282 28 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
qwe987544 2013-12-05
  • 打赏
  • 举报
回复
clear是不清空List内存的亲。
superyjcqw123 2013-07-03
  • 打赏
  • 举报
回复
通过排除法,问题已找到,是ibatis 频繁读取数据库的问题,换成jdbc就好了
superyjcqw123 2013-07-02
  • 打赏
  • 举报
回复
附上异常信息
2013-7-2 11:21:21 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet SpringMVC threw exception
java.lang.OutOfMemoryError: Java heap space
at oracle.jdbc.driver.OraclePreparedStatement.setupBindBuffers(OraclePreparedStatement.java:2764)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:9348)
at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:211)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.logicalcobwebs.proxool.ProxyStatement.invoke(ProxyStatement.java:100)
at org.logicalcobwebs.proxool.ProxyStatement.intercept(ProxyStatement.java:57)
at $java.sql.PreparedStatement$$EnhancerByProxool$$13fa0d1f.executeBatch(<generated>)
at com.ibatis.sqlmap.engine.execution.SqlExecutor$Batch.executeBatch(SqlExecutor.java:611)
at com.ibatis.sqlmap.engine.execution.SqlExecutor.executeBatch(SqlExecutor.java:118)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.executeBatch(SqlMapExecutorDelegate.java:759)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.executeBatch(SqlMapSessionImpl.java:184)
at com.founder.ec.base.dao.impl.BaseDaoImpl$2.doInSqlMapClient(BaseDaoImpl.java:234)
at org.springframework.orm.ibatis.SqlMapClientTemplate.execute(SqlMapClientTemplate.java:200)
at com.founder.ec.base.dao.impl.BaseDaoImpl.batchUpdate(BaseDaoImpl.java:228)
at com.founder.ec.seo.service.impl.WordServiceImpl.batchUpdate(WordServiceImpl.java:550)
at com.founder.ec.seo.service.impl.WordServiceImpl$$FastClassByCGLIB$$30ed5a4b.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:688)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80)
at com.founder.ec.common.aop.MethodAOP.doLog(MethodAOP.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspect
北吹 2013-06-28
  • 打赏
  • 举报
回复
artWords.clear().
引用 16 楼 superyjcqw123 的回复:
[quote=引用 15 楼 beichui 的回复:] [quote=引用 12 楼 superyjcqw123 的回复:] [quote=引用 5 楼 beichui 的回复:] 逻辑上没有问题,但是你的batchList是在每次循环末尾清掉的,这个时候如果内存稀缺,GC会启动,内存就不会有问题。 但可能存在这种情况,你的某一次循环内,batchList.clear()方法被调用前,内存已经不够了,比如有几个超大的Article对象,这个时候Article对象都是有引用的,GC启动了也无法清掉,这个时候会报内存溢出。
我把循环改成500也不行[/quote] 你统计下,最大的500行数据的总大小,跟你的内存比较下。[/quote] 平均每1000条占3M[/quote] 那就不是这个问题啊,内存那个循环,每次artWords用完了,artWords.clear()一下试试。
superyjcqw123 2013-06-28
  • 打赏
  • 举报
回复
引用 15 楼 beichui 的回复:
[quote=引用 12 楼 superyjcqw123 的回复:] [quote=引用 5 楼 beichui 的回复:] 逻辑上没有问题,但是你的batchList是在每次循环末尾清掉的,这个时候如果内存稀缺,GC会启动,内存就不会有问题。 但可能存在这种情况,你的某一次循环内,batchList.clear()方法被调用前,内存已经不够了,比如有几个超大的Article对象,这个时候Article对象都是有引用的,GC启动了也无法清掉,这个时候会报内存溢出。
我把循环改成500也不行[/quote] 你统计下,最大的500行数据的总大小,跟你的内存比较下。[/quote] 平均每1000条占3M
北吹 2013-06-28
  • 打赏
  • 举报
回复
引用 12 楼 superyjcqw123 的回复:
[quote=引用 5 楼 beichui 的回复:] 逻辑上没有问题,但是你的batchList是在每次循环末尾清掉的,这个时候如果内存稀缺,GC会启动,内存就不会有问题。 但可能存在这种情况,你的某一次循环内,batchList.clear()方法被调用前,内存已经不够了,比如有几个超大的Article对象,这个时候Article对象都是有引用的,GC启动了也无法清掉,这个时候会报内存溢出。
我把循环改成500也不行[/quote] 你统计下,最大的500行数据的总大小,跟你的内存比较下。
superyjcqw123 2013-06-28
  • 打赏
  • 举报
回复
引用 11 楼 lyh_zxc 的回复:
list = commonDao.queryForList("Article.getArticlePage", article); 这个list用完后最好设成null,以便gc回收。 Article a = new Article(); 这个a的创建最好要放到所有循环的外面,用完后设成null。
关于list 对象 设为空,之前都试过,没什么效果
superyjcqw123 2013-06-28
  • 打赏
  • 举报
回复
引用 8 楼 l_9style 的回复:
List<Word> artWords = getWords(art.getId()); 
这句把List<Word> artWords 放到for循环外面吧,不然每循环一次,相当于多new一个对象
这个之前试过,没效果
superyjcqw123 2013-06-28
  • 打赏
  • 举报
回复
引用 5 楼 beichui 的回复:
逻辑上没有问题,但是你的batchList是在每次循环末尾清掉的,这个时候如果内存稀缺,GC会启动,内存就不会有问题。 但可能存在这种情况,你的某一次循环内,batchList.clear()方法被调用前,内存已经不够了,比如有几个超大的Article对象,这个时候Article对象都是有引用的,GC启动了也无法清掉,这个时候会报内存溢出。
我把循环改成500也不行
小猴168 2013-06-28
  • 打赏
  • 举报
回复
list = commonDao.queryForList("Article.getArticlePage", article); 这个list用完后最好设成null,以便gc回收。 Article a = new Article(); 这个a的创建最好要放到所有循环的外面,用完后设成null。
careers1111 2013-06-28
  • 打赏
  • 举报
回复
内存搞大点内存搞大点
coooliang 2013-06-28
  • 打赏
  • 举报
回复
你能不能不要什么都放在循环里做啊。 一个一个for按顺序来好吗。。。
l_9style 2013-06-28
  • 打赏
  • 举报
回复
List<Word> artWords = getWords(art.getId()); 
这句把List<Word> artWords 放到for循环外面吧,不然每循环一次,相当于多new一个对象
Abner999 2013-06-28
  • 打赏
  • 举报
回复
换成LinkedList看行不行
Abner999 2013-06-28
  • 打赏
  • 举报
回复
看了下ArrayList最大存储内容好像是4G,是不是你的batchList内容存储的太大了
superyjcqw123 2013-06-28
  • 打赏
  • 举报
回复
引用 23 楼 panhaichun 的回复:
每当 batchList 里面元素达到一定数量时,比如说1000条。你就要处理一次,然后再clear
怎么个处理法
panhaichun 2013-06-28
  • 打赏
  • 举报
回复
调整一下jdbc connection的fetchSize参数
panhaichun 2013-06-28
  • 打赏
  • 举报
回复
每当 batchList 里面元素达到一定数量时,比如说1000条。你就要处理一次,然后再clear
无聊找乐 2013-06-28
  • 打赏
  • 举报
回复
用list全装着? 建议你换64位系统,上64位jdk,用8G的内存, 设置jvm的Xmx参数看看
superyjcqw123 2013-06-28
  • 打赏
  • 举报
回复
用监控发现是jdbc内部操作占用大量内存
加载更多回复(6)

67,549

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧