是否有更有效的方法来协调大型数据集?

时间:2009-07-09 05:05:13

标签: c# optimization memory comparison

我的任务是调和两个大数据集(两个大的事务列表)。基本上我将两个数据源中的相关字段提取为两个相同格式的文件,然后比较文件以查找A中但不在B中的任何记录,反之亦然,并报告它们。我在my best efforts achieving this (click if interested).

上写了一篇博客文章

它的要点是将两个数据集加载到一个大的哈希表中,其中键是行,每次出现在文件A中时值为+1,每次出现在文件B中时为-1。然后在最后,我查找值为!= 0的任何键/值对。

我的算法看起来足够快(2 * 100mb文件需要10秒),但它有点内存密集型:280mb来比较两组100mb文件,我希望将其降低到100mb峰值内存使用率,并且可能如果两个数据集按大致相同的顺序排序,则降低。

有什么想法吗?

另外,如果SO过于开放,请告诉我。

4 个答案:

答案 0 :(得分:2)

我只使用shell和perl在unix上的脚本中做了类似的事情,但理论可能会过时。

步骤1,对两个文件进行排序,使它们按照相同的标准排序。我使用unix sort命令来执行此操作(我需要唯一标志,但您只需要某种内存高效的文件排序)。这可能是弄清楚你自己的棘手部分。

步骤2,打开两个文件,并基本上逐行扫描(如果是二进制格式,则按记录记录)。如果左侧文件中的行等于右侧文件中的行,则行匹配并继续前进(记住我们已经对文件进行了排序,因此最小的记录应该是第一个)。

如果左侧记录大于右侧记录,则表示您的记录丢失,将其添加到列表中,然后读取右侧文件中的下一行。只是你再次检查。同样的事情适用于你正确的记录是否更大,比你剩下的记录丢失,报告并继续。

扫描记录应该非常有效。它可能没有那么快,但对我来说,我能够通过多次传递来查看几个数据,并在几分钟内查看不同的字段。

答案 1 :(得分:1)

我能想到的唯一方法是不立即将所有数据加载到内存中。如果你改变你处理它的方式,以便它一次抓取每个文件的一点,它会减少你的内存占用量,但会增加你的磁盘IO,这可能会导致更长的处理时间。

答案 2 :(得分:1)

一种选择可能是更改数据的内存格式。如果您的数据是以文本形式存储的一系列数字,则将它们作为整数存储在内存中可能会降低内存占用量。

另一种选择可能是使用某种外部程序对行进行排序 - 然后您可以按顺序对这两个文件进行简单扫描,以寻找差异。

回到你的问题,280mb听起来很高,比较一对100mb文件 - 你只是将一个加载到内存(较小的一个),只是滚动到另一个,对吧?正如你所描述的那样,我认为你不需要在内存中同时拥有两者的全部内容。

答案 3 :(得分:0)

使用此方法,您必须始终将其中一个文件的内容放在内存中。就内存而言,只需占用一半文件就会更有效。将它与第二个文件逐行比较。然后将下半场记忆并做同样的事情。这种重叠将确保没有错过任何记录。并且不需要暂时存储整个文件。