我有一个要求,在其中一个报告中,我需要从数据库中获取大约1000万条记录并将它们传输到Excel。
应用程序是客户端 - 服务器模型,其中服务器端逻辑用EJB和EJB编写。客户端是用Swing编写的。
现在我的问题是当我尝试从Resultset填充Java的对象时,如果结果集的大小更多(>> 100000)那么它会在Java端抛出Out of Memory Error。
有人能让我知道Java应如何处理这种情况吗?我需要将所有记录从服务器传输到客户端,然后我需要根据从服务器端检索的数据构建Excel报告。
答案 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的限制,所以你也要照顾好。