从数据库中获取记录时出现java.lang.OutOfMemory错误

时间:2010-03-19 13:23:01

标签: java jdbc

当我尝试获取大约20,000条记录并返回到ArrayList时,它会抛出java堆空间错误。

   JdbcTemplate select = new JdbcTemplate(dataSource);
            String SQL_SELECT_XML_IRP_ADDRESS = " SELECT * FROM "+ SCHEMA +".XML_ADDRESS "+
                                                    " WHERE FILE_NAME = ? ";
            Object[] parameters=new Object[] {xmlFileName};
            return (ArrayList<XmlAddressDto> ) select.query(SQL_SELECT_XML_ADDRESS,
                    parameters,new XmAddressMapExt());

我们的数据库是Oracle并使用oracle瘦驱动程序 这有什么解决方案吗?我该如何有效地处理这个问题?

4 个答案:

答案 0 :(得分:3)

如果不了解系统的详细信息,答案很难,但有几个选项:

  • 增加JVM的内存(请参阅关于SO的许多其他问题)
  • 避免一次处理所有记录;尝试抓住你的查询的一个子集,处理它,然后重复,而不是一次性插入所有内容
  • 尝试减少您阅读的数据量:您真的需要做SELECT *吗?

答案 1 :(得分:1)

您是否需要同时保留所有20,000条记录的所有字段?

据推测,您需要处理它们并从这些数据中产生一些东西。 然后构建你的算法,使其在时间读取N个记录(比如说100),处理它们,然后继续下一个。

您可能还想看一下Spring的SqlQuery类,它可以帮助您对SQL查询返回的结果集执行计算。

答案 2 :(得分:1)

你真的需要将所有20000结果保存在内存中吗?

如果您只想处理所有20000个结果,则应对每行使用RowCallbackHandler处理,setFetchSize()以避免完全选择内存。

答案 3 :(得分:1)

这里的核心问题是您可能没有足够的内存来存储内存中20,000个XmlAddressDto对象的副本。有两种选择:

  1. 添加更多内存(或更大的堆,在启动JVM时使用-Xmx)
  2. 使用内存中的子集 - 懒惰地初始化一个集合(例如,仅缓存最后200个或左右的条目,通过db访问其他条目)。你甚至可以将这个集合包装在List界面中,这可能会完成你想要做的事情 - 虽然你必须要小心访问,或者像迭代它的成员那样
  3. 了解如何缩小XML对象 - 如果DTO是完整的树对象,可能存储二进制或字符串表示,如果需要使用它,则解压缩它 - 特别是如果您要通过完整的XML到其他一些代码可以使用。