我的任务是调和两个大数据集(两个大的事务列表)。基本上我将两个数据源中的相关字段提取为两个相同格式的文件,然后比较文件以查找A中但不在B中的任何记录,反之亦然,并报告它们。我在my best efforts achieving this (click if interested).
上写了一篇博客文章它的要点是将两个数据集加载到一个大的哈希表中,其中键是行,每次出现在文件A中时值为+1,每次出现在文件B中时为-1。然后在最后,我查找值为!= 0的任何键/值对。
我的算法看起来足够快(2 * 100mb文件需要10秒),但它有点内存密集型:280mb来比较两组100mb文件,我希望将其降低到100mb峰值内存使用率,并且可能如果两个数据集按大致相同的顺序排序,则降低。
有什么想法吗?
另外,如果SO过于开放,请告诉我。
答案 0 :(得分:2)
我只使用shell和perl在unix上的脚本中做了类似的事情,但理论可能会过时。
步骤1,对两个文件进行排序,使它们按照相同的标准排序。我使用unix sort命令来执行此操作(我需要唯一标志,但您只需要某种内存高效的文件排序)。这可能是弄清楚你自己的棘手部分。
步骤2,打开两个文件,并基本上逐行扫描(如果是二进制格式,则按记录记录)。如果左侧文件中的行等于右侧文件中的行,则行匹配并继续前进(记住我们已经对文件进行了排序,因此最小的记录应该是第一个)。
如果左侧记录大于右侧记录,则表示您的记录丢失,将其添加到列表中,然后读取右侧文件中的下一行。只是你再次检查。同样的事情适用于你正确的记录是否更大,比你剩下的记录丢失,报告并继续。
扫描记录应该非常有效。它可能没有那么快,但对我来说,我能够通过多次传递来查看几个数据,并在几分钟内查看不同的字段。
答案 1 :(得分:1)
我能想到的唯一方法是不立即将所有数据加载到内存中。如果你改变你处理它的方式,以便它一次抓取每个文件的一点,它会减少你的内存占用量,但会增加你的磁盘IO,这可能会导致更长的处理时间。
答案 2 :(得分:1)
一种选择可能是更改数据的内存格式。如果您的数据是以文本形式存储的一系列数字,则将它们作为整数存储在内存中可能会降低内存占用量。
另一种选择可能是使用某种外部程序对行进行排序 - 然后您可以按顺序对这两个文件进行简单扫描,以寻找差异。
回到你的问题,280mb听起来很高,比较一对100mb文件 - 你只是将一个加载到内存(较小的一个),只是滚动到另一个,对吧?正如你所描述的那样,我认为你不需要在内存中同时拥有两者的全部内容。
答案 3 :(得分:0)
使用此方法,您必须始终将其中一个文件的内容放在内存中。就内存而言,只需占用一半文件就会更有效。将它与第二个文件逐行比较。然后将下半场记忆并做同样的事情。这种重叠将确保没有错过任何记录。并且不需要暂时存储整个文件。