java.lang.OutOfMemoryError:执行数百万次查询时发生java堆空间错误

java.lang.OutOfMemoryError:执行数百万次查询时发生java堆空间错误,java,out-of-memory,Java,Out Of Memory,在我的应用程序中,我需要对MySQL数据库执行数百万次查询。代码如下所示: for (int i=0; i< num_rows ; i++) { String query2="select id from mytable where x='"+ y.get(i) "'"; Statement stmt2 = Con0.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_

在我的应用程序中,我需要对MySQL数据库执行数百万次查询。代码如下所示:

for (int i=0; i< num_rows ; i++) {
   String query2="select id from mytable where x='"+ y.get(i) "'";              
   Statement stmt2 = Con0.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);     
   ResultSet rs2 = stmt2.executeQuery(query2);    
   ... // process result in rs2
   rs2.close(); 
}
for(int i=0;i
其中,行数约为200万。600k循环后,java报告错误并退出:

java.lang.OutOfMemoryError:java堆空间错误

我的密码出了什么问题?我应该如何避免这样的错误


提前谢谢

也关闭您的语句。

使用preparedStatement,因为每个循环中只有X的值发生变化,在de-loop之外声明应该会有所帮助。至少在显示的代码中,您还没有关闭所使用的语句,这可能无助于垃圾收集器释放所使用的内存。

语句在这里不是好的解决方案。请尝试以下代码:

PreparedStatement pre = Con0.prepareStatement("select id from mytable where x=?");

for (int i=0; i< num_rows ; i++) {
   pre.setString(1, y.get(i));
   ResultSet rs2 = pre.executeQuery();
   ... // process result in rs2
   rs2.close(); 
   pre.clearParameters();
}
pre.close();
PreparedStatement pre=Con0.prepareStatement(“从mytable中选择id,其中x=?”;
对于(int i=0;i
假设您对所有查询使用单一连接,并且假设您的代码比您向我们展示的代码更复杂,那么确保在完成每个语句和每个结果集时关闭它们是至关重要的。这意味着您需要这样的try/finally块:

for (int i=0; i< num_rows ; i++) {
  String query2="select id from mytable where x='"+ y.get(i) "'";              
  Statement stmt2 = Con0.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);     
  ResultSet rs2 = null;   
  try {
    rs2 = stmt2.executeQuery(query2);    
    ... // process result in rs2
  } finally {
    try {
      stmt2.close();
    } catch (SQLException sqle) {
      // complain to logs
    }
    try {
      if (rs2 != null) { rs2.close(); }
    } catch (SQLException sqle) {
    }
  }
}
for(int i=0;i

如果您不积极地、果断地关闭所有结果集和语句对象,并且如果您足够快地执行请求,您的内存将耗尽。

我不知道您接受的答案是否解决了您的问题,因为它不会改变任何可能导致问题的因素

问题在于ResultSet缓存查询返回的所有行时,这些行可以在遍历集合时存储,也可以预取。我对PostgreSQL JDBC驱动程序也有类似的问题,它在非事务模式下运行时忽略了游标获取大小


JDBC驱动程序应该使用游标进行此类查询,因此您应该查看驱动程序关于fetchSize参数的文档。或者,您可以自己管理游标,执行SQL命令来创建游标并获取下一个X行。

您在这里对数据做什么?SQL数据库无法非常有效地处理数百万个查询。这是因为每个查询都有相对较高的开销。您最好将查询分批处理为100个块。我采用了约翰和安杰洛的方法,效果很好。也谢谢其他人。