Java - 巨大的数据检索

时间:2011-03-09 13:00:50

标签: java performance out-of-memory

我有一个要求,在其中一个报告中,我需要从数据库中获取大约1000万条记录并将它们传输到Excel。

应用程序是客户端 - 服务器模型,其中服务器端逻辑用EJB和EJB编写。客户端是用Swing编写的。

现在我的问题是当我尝试从Resultset填充Java的对象时,如果结果集的大小更多(>> 100000)那么它会在Java端抛出Out of Memory Error。

有人能让我知道Java应如何处理这种情况吗?我需要将所有记录从服务器传输到客户端,然后我需要根据从服务器端检索的数据构建Excel报告。

5 个答案:

答案 0 :(得分:1)

我会使用LIMIT命令将结果集分解为更小的块(mySQL,不知道这是否在其他数据库服务器中)。像这样的伪代码:

long recsToget = 50000;
long got = recsToGet;
long offset = 0;
while ( got == recsToGet )
{
  got = getNextBatchFromDb( offset );
  writeBatchToCsv();
  offset += recsToGet; //increase your OFFSET each time
}

我会在getNextBatchFromDb()函数的SQL查询中使用LIMIT和OFFSET,如下所示:

select * from yourtable LIMIT 50000 OFFSET 100000

其中OFFSET是开始读取的位置,LIMIT是要读取的数字。

通过执行此操作,您可以在较小的块中读取大数据集并每次更新CSV直到完成。您知道当getNextBatchFromDb()返回的行数小于recsToGet时,已读取所有记录。

答案 1 :(得分:0)

您可以使用-Xmx开关增加JVM可用的内存量(例如-Xmx1024m将JVM设置为最多1GB的内存)。

如果这不是一个选项,或者您已经完成了此操作,唯一的选择是重写服务器以分阶段而不是一次性返回结果。如何执行此操作取决于服务器实现的具体细节。

答案 2 :(得分:0)

您需要尽可能多地处理数据库端的数据。然后,一旦有了数据,就会在数据库中或者至少在某种缓冲区中读取数据时写出数据,这样就不会加载Java程序中的所有数据。

答案 3 :(得分:0)

您可以使用基本类型,而不是使用Object。注意:除非您的客户端比服务器更多内存,否则没有必要将所有这些数据发送给客户端。

通常,服务器会为客户端生成报告。这最大化了服务器完成的工作,并减少了发送到客户端的数据。 Excel无法处理工作表中超过一百万行,其图表无法处理超过32,000个点。我建议你在服务器上做报告。

答案 4 :(得分:0)

对象不是这种情况的好选择。以下是处理此问题的几种选择。

1)在从数据库中检索记录时应用分页并附加到您的报告中。

2)此选项取决于数据库服务器。某些数据库服务器能够将任何查询的输出导出到平面文件。检查你的数据库是否支持这个。然后在导出后,您可以从平面文件中读取内容并生成报告。

许多朋友已经提到了excel的限制,所以你也要照顾好。