从大型结果集生成CSV时,如何限制内存使用?

时间:2010-08-25 17:12:38

标签: oracle spring memory-management jdbc jdbctemplate

我在Spring中有一个Web应用程序,它具有从来自大型Oracle数据库的结果集生成CSV / Excel电子表格的功能要求。预期的行数在300,000 - 1,000,000范围内。处理时间并不像保持应用程序稳定那么大 - 而且现在,非常大的结果集会导致内存不足并崩溃。

在这种正常情况下,我会使用分页并让UI一次显示有限数量的结果。但是,在这种情况下,我需要能够在单个文件中生成整个集合,无论它有多大,都可以离线使用。

我已将问题隔离到ParameterizedRowMapper,用于将结果集转换为对象,这就是我被卡住的地方。

我可以使用哪些技术来控制此操作?分页仍然是一种选择吗?

4 个答案:

答案 0 :(得分:1)

一个简单的答案:

使用JDBC记录集(或类似的,具有适当的数组/提取大小)并将数据写回LOB,临时或返回数据库。

另一种选择:

使用数据库中的PL / SQL以CSV格式为您的记录集使用UTL_FILE编写文件。由于文件将位于数据库服务器上,而不是客户端上,因此使用UTP_SMTP或JavaMail使用Java存储过程来邮寄文件。毕竟,如果有人要反复观看沙漏翻转等待生成100万行记录集,我会感到惊讶。

答案 1 :(得分:1)

您可以单独处理每一行并使用输出流将输出直接发送到Web浏览器,而不是将整个文件加载到内存中。例如。在servlet API中,您可以从ServletResponse.getOutputStream()获取输出流,然后简单地将结果CSV行写入该流。

答案 2 :(得分:0)

我会推迟这些要求 - 听起来很人性化。 如果您的应用程序出现故障,或者在用户查看该数据之前电源耗尽,会发生什么?

从上面的评论中,听起来你知道答案 - 你需要文件系统或oracle访问,以便完成你的工作。

您被要求生成一些不能被sql重复的数据? 如果它是可重复的,您只需将数据页面一次发送回用户。

由于此报告,我猜测,与数据的当前状态有关,如果无法将其传输给用户,则需要将结果存储在某处。我在oracle中编写了一个存储过程 - 不要在网络上来回传输数据要快得多。如果你有特殊的工具或它更容易,听起来在java方面这样做是没有错的。

您可以安排此报告每周运行一次吗?

答案 3 :(得分:0)

您是否考虑过具有1,000,000行的Excel电子表格的效果?