我在weblogic上使用spring。我将获取大小设置为500,以便更快地从db中获取数据。但这会导致记忆问题。下面是一个示例:
http://webmoli.com/2009/02/01/jdbc-performance-tuning-with-optimal-fetch-size/
我的问题是如何释放这个记忆?运行GC不起作用,我猜它不能工作,因为连接池中的连接是活动的。
代码:
public List<Msisdn> getNewMsisdnsForBulkSmsId(String bulkSmsId,String scheduleId,final int msisdnCount) throws SQLException {
JdbcTemplate jdbcTemplate = getJdbcTemplate();
jdbcTemplate.setFetchSize(500);
jdbcTemplate.setMaxRows(msisdnCount);
jdbcTemplate.query("select BULKSMS_ID, ? as , STATUSSELECTDATE, DELIVERYTIME, ID, MESSAGE from ada_msisdn partition (ID_"+bulkSmsId+") where bulksms_id = ? and status = 0 and ERRORCODE = 0 and SCHEDULEID is null for update skip locked", new Object[]{scheduleId,bulkSmsId}, MsisdnRowMapper.INSTANCE);
//Also i tried to close connection and run gc, this does not free the memory too.
//jdbcTemplate.getDataSource().getConnection().close();
//System.gc();
return null;
}当我将获取大小设置为10时,如果将获取大小设置为500,堆大小为206 MB,则堆大小为12 MB。
谢谢
发布于 2012-01-11 17:06:36
对添加的示例代码进行更新,等等:
听起来,您只需要使用小于500的值,但这使我认为您返回的数据比结果集映射器实际使用的数据多得多。
现在我看到您正在将所有映射的结果存储在一个List中,我想说,使用fetch大小看到的问题很可能是次要的问题。List<Msisdn>和一组获取的ResultSet行所需的组合内存空间正将您推过可用内存。
msisdnCount的价值是什么?如果它大于500,那么您可能在list中使用的内存比在ResultSet的500个记录中的内存要多。如果它小于500,那么当您将获取大小设置为msisdnCount时,内存问题也会发生,并且在min(msisdnCount, 500)和10之间的某个值时,错误会消失。
将所有结果加载到列表中,然后处理它们,这是一种模式,通常会导致内存耗尽。常见的解决方案是使用流。如果您可以在每一行进来时处理它,而不将所有映射结果存储在list中,那么您就可以避免内存问题。
我在Spring核心包中没有看到任何流支持,但是如果我找到它,我会更新它。
--
如果要检索的行中的数据足够大,以至于取500行将耗尽堆,则必须一次返回较少的数据或每次获取较少的行。
您可能会发现,您正在代码中的某个地方存储获取的行,这意味着它不是耗尽内存的ResultSet。例如,您可能要将所有行复制到某个集合实例。
我将查看每一行中数据的大小,并尝试减少可能包含大型数据类型的不需要的列,然后尝试简单地加载数据并迭代结果,而不执行正常的处理(这可能是将数据存储在某个地方),以查看一次可以用内存加载多少行。如果内存不足,需要提取500行数据,那么一定是在拖放大量数据。如果您没有实际使用这些数据,那么您就在浪费CPU和网络资源以及内存。
编辑:您还可能希望设置游标行为,以便为JDBC驱动程序提供更多帮助,以了解它可以丢弃什么。例如,您可以使用ResultSet.TYPE_FORWARD_ONLY、ResultSet.CONCUR_READ_ONLY来准备语句。http://docs.oracle.com/javase/6/docs/api/index.html?java/sql/ResultSet.html
https://stackoverflow.com/questions/8823151
复制相似问题