2009-05-18 78 views
1

我有一个要求,我必须从数据库中选择大约6000万条记录。一旦我有了ResultSet中的所有记录,那么我必须根据客户需求(日期格式和数字格式)合成一些列,然后我必须将所有记录写入文件(辅助内存)中。场景的最佳设计

  • 目前,我正在从数据库中选择一天的记录(7天选择7天)并将它们放入HashMap。从HashMap中读取并合成一些列,最后写入文件(单独文件7天)。
  • 最后,我将所有7个文件合并到一个文件中。

  • 但是这整个过程需要6个小时才能完成。为了改善这一过程,我创建了7天7天的线程,所有线程都编写了单独的文件。

  • 最后,我将所有7个文件合并到一个文件中。这个过程需要2个小时。但是我的程序在1小时后会进入OutOfMemory。

请建议最好的设计,这种情况下,我应该使用一些缓存机制,如果是的话,哪一个又如何呢?

注意:客户端不希望在数据库中更改任何内容,如创建索引或存储过程,他们不想触摸数据库。 在此先感谢。

+0

你能告诉我们你正在使用的RDMS吗?这将影响可能可用的面向数据库的解决方案。 另外,您可以告诉我们数据库是专为事务处理(高度规范化)还是更多分析处理(高度非规范化)设计的? – 2009-05-18 16:37:11

+0

客户端不想在数据库中更改任何内容。他们还没有准备好创建新的索引或SP或对表格进行规范化。 – 2009-05-18 16:48:47

回答

4

您是否需要将所有记录存储在内存中才能格式化它们?您可以尝试通过流程和文件的权限对记录进行流式处理。如果你甚至能够进一步分解查询,你可能能够开始处理结果,而你仍然可以检索它们。

根据你的数据库后端,他们可能有工具来帮助解决这个问题,比如SSIS for Sql Server 2005+。

编辑

我是一个.NET开发人员,所以让我提出什么,我会在.NET做,希望你可以转换成在Java端媲美的技术。

ADO.Net有一个DataReader,它是一个结果集的只读,只读(Firehose)游标。它在查询执行时返回数据。这个非常重要。从本质上讲,我的逻辑是:

IDataReader reader=GetTheDataReader(dayOfWeek); 

while (reader.Read()) 
{ 
    file.Write(formatRow(reader)); 
} 

由于这一点的同时,我们正在返回你不打算上我猜测的网络接入块行正在执行对你是一个巨大的瓶颈。这里的关键是我们没有将这些内容长时间存储在内存中,因为我们循环读取器会放弃结果,并且文件会将行写入磁盘。

0

取决于您使用的数据库,但如果是SQL Server,我会推荐使用类似SSIS的方法来执行此操作,而不是编写程序。

+0

客户端尚未准备好更改数据库中的任何内容。没有索引和存储过程。 – 2009-05-18 16:46:57

2

我想乔什的建议是这样的:

你有循环,在那里你目前通过你查询的所有结果记录(只是用伪这里代码):

while (rec = getNextRec()) 
    { 
    put in hash ... 
    } 

for each rec in (hash) 
    { 
    format and save back in hash ... 
    } 

for each rec in (hash) 
    { 
    write to a file ... 
    } 

instead, do it like this: 

while (rec = getNextRec()) 
    { 
    format fields ... 
    write to the file ... 
    } 

那么你在内存中一次不会有超过1条记录......并且您可以处理无限数量的记录。

1

显然一次读取6000万条记录会耗尽你所有的记忆 - 所以你不能这样做。 (即你的7线程模型)。每次读取6000万条记录会耗尽您所有的时间 - 所以您无法做到这一点(即您最初的读取文件模型)。

所以....你将不得不妥协,并做一些两者。

Josh说得对 - 打开一个光标到你的数据库,它只是简单地读取下一个记录,一个接一个地以最简单,功能最强的方式。一个“firehose”游标(或者称为只读游标,只向前游标)就是你想要的,因为它在数据库上施加的负载最小。数据库不会让您更新记录,也不会让您在记录集中向后退出,而您不希望这样做,因此它不需要处理记录的内存。

现在你有了这个光标,DB每次给你一条记录 - 读取它,并将它写入一个文件(或几个文件),这应该会很快完成。然后你的任务是将文件合并到1,并且顺序正确,这相对容易。

鉴于您必须处理的记录数量,我认为这是您的最佳解决方案。

但是......无论如何,看到你做得相当不错,为什么不减少线程的数量,直到你处于你的内存限制之内。批量处理在一夜之间运行的很多公司,这似乎是另一个过程。