我有一个文件A,其中包含40Millon附近的一些记录。我有另一个文件B,其中包含70Millon左右的一些记录。现在我必须遍历文件A,对于每个记录搜索,如果文件B中有条目。如果是,则在文件C中写入条目。
请提出有关如何实现这一目标的建议,而不会浪费内存并且时间最短。我已经尝试过apache lucene,但它有额外的创建索引的开销,因为文件B有7000万条记录每天都会改变(即我们从外部系统获取这个文件)每天重新创建索引是非常难的
答案 0 :(得分:2)
您可以使用Chronicle Map。
您应该可以在几秒到几分钟内加载7000万条记录,具体取决于记录的大小。如果需要,您可以实时更新记录。
由于Chronicle Map是持久存在且不在堆外,如果有帮助,你可以离线或在另一个进程中执行此操作。
或者您可以使用数据库,批量加载此类表格不应该花费超过几分钟的时间。
答案 1 :(得分:1)
如果数据库不是一个选项,我有一个想法:
预处理您的第二个文件:抓取并按字母顺序对其进行排序:
Anna
Aqua
Claire
Jeremy
Joseph
Vill
现在创建一个文件,将每个字母字符映射到用作名称起始字符的行号:
A,0
C,2
J,3
V,5
之前的步骤称为预处理,您应该在编译程序之前执行这些步骤。显然,对这样一个巨大的文件进行排序会花费很多时间,但是如果使用这种方法,那么部署的程序将会快得多:
当您迭代第一个文件时,假设您找到了Joseph
。你所做的是获取第一个字符J
,然后使用映射来确定使用该字符的第一个行号。映射将生成3
,因此您将迭代第二个文件到这样的行号。这样可以节省大量时间,因为您可以在显然不符合搜索条件的多行上跳过equals()
。要查找Joseph
,您只需要检查Jeremy
然后Joseph
。
现在您已了解此技术,您可以通过使用两个级别来提高效率:对于字母表中的每个字符,为字母表中的每个字符创建另一个映射。在J
的情况下,它将是
JE,3
JO,4
由于您正在寻找Joseph
,因此您可以轻松确定开始寻找它的行号是第四行,从而跳过更多的比较。
你可以在更多级别上执行此操作:三,四等......由您来决定哪一个是您的最佳选择。映射不会占用太多空间,它们可以通过跳过不必要的条目来节省大量时间。
显而易见的缺点是,预处理包含7000万条目的文件非常详尽 - 但这是您的最终用户无需体验的内容。
这是一种方法。
注意:您仍需要迭代第二个文件的每一行以达到所需的行号。关键是你不需要进行任何类型的比较 - 你会发现这将为你节省大量的处理时间。
答案 2 :(得分:0)
假设您没有足够的内存来加载数据,并且没有便于索引的数据库,最好的办法是使用sort-merge join。
实质上,按连接/查找条件对两个文件进行排序,然后并行读取文件(“合并”)。