Perl处理一万亿条记录



寻求一些建议或见解,了解我认为在PERL中比较文本文件的简单方法。

假设您有90000个结构相似的文本文件,比如说它们有一个共同的主题,每个主题中都有少量独特的数据。

我的逻辑是简单地循环遍历文件(为了简单起见,分成1000行),然后循环遍历文件的#。。。90000-然后再次循环浏览90000个文件以相互比较。这几乎变成了一个由无数条线或过程组成的无休止的循环。

现在,这里的强制性步骤是"删除"除我们正在处理的文件外的任何文件中的任何行。最终目标是将所有文件清除为整个集合中唯一的内容,即使这意味着某些文件最终为空。

我说的是文件,但这可能是数据库中的行,也可能是数组中的元素。(我已经试过了。)到目前为止,最快的解决方案是将所有文件加载到mysql中,然后运行UPDATE表SET column=REPLACE(列,查找,替换);在使用mysql时也尝试了Parallel::ForkManager。

最慢的方法实际上会耗尽我32 GB的内存——那就是将所有90k个文件加载到一个数组中。90k个文件根本不起作用,像1000个这样的小批量可以很好地工作,但与其他89000个文件相比就不行了。

服务器规格(如果有帮助):单四核E3-1240 4核x 3.4Ghz w/HT 32GB DDR3 ECC RAM 1600MHz 1x256SSD

那么工程师如何解决这个问题呢?我只是PERL黑客。。。

用文件名(可能还有行号)标记每一行,并使用Sort::External对所有行进行排序。然后,您可以按顺序读取排序后的记录,并只在结果文件中写入一行唯一的行。

如果您可以处理任意小的错误,那么Bloom过滤器就是完美的选择。

引用维基百科的话:"Bloom过滤器是一种节省空间的概率数据结构,用于测试元素是否是集合的成员。假阳性匹配是可能的,但假阴性不可能;即查询返回‘可能在集合中’或‘绝对不在集合中"。

本质上,您将使用k个散列将每一行散列到一个位数组上的k个点。每次遇到新行时,如果k个哈希索引中至少有一个具有"0"位,则可以保证您没有看到它。您可以阅读Bloom过滤器,了解如何调整阵列的大小,并选择k使误报任意小。

然后浏览文件,删除得到正匹配的行,或者将负匹配的行复制到新文件中。

使用外部合并排序算法对项目进行排序,并在合并阶段删除重复项。

实际上,只需使用-u标志调用sort命令就可以高效地完成此操作。来自Perl:

system "sort -u @files >output";

sort命令可能会提供几个可调整的参数以提高其性能。例如,并行进程的数量或它可以分配的内存量。

最新更新