C# 删除大型文本文件中的所有重复项
我真的被这个问题难住了,因此我已经停止工作一段时间了。我处理大量数据。我每周获得大约200gb的.txt数据。数据范围可达5亿行。很多都是重复的。我想只有20gb是独一无二的。我有几个自定义程序,包括散列删除重复,外部删除重复,但似乎没有工作。最近一次是使用临时数据库,但删除数据需要几天时间 所有这些程序的问题是,它们在某一点后崩溃,在花了大量的钱在这些程序上之后,我想我会上网看看是否有人能帮忙。我知道这已经在这里得到了回答,我花了3个小时在这里阅读了大约50个线程,但似乎没有一个像我一样的问题,即巨大的数据集C# 删除大型文本文件中的所有重复项,c#,java,c++,perl,duplicates,C#,Java,C++,Perl,Duplicates,我真的被这个问题难住了,因此我已经停止工作一段时间了。我处理大量数据。我每周获得大约200gb的.txt数据。数据范围可达5亿行。很多都是重复的。我想只有20gb是独一无二的。我有几个自定义程序,包括散列删除重复,外部删除重复,但似乎没有工作。最近一次是使用临时数据库,但删除数据需要几天时间 所有这些程序的问题是,它们在某一点后崩溃,在花了大量的钱在这些程序上之后,我想我会上网看看是否有人能帮忙。我知道这已经在这里得到了回答,我花了3个小时在这里阅读了大约50个线程,但似乎没有一个像我一样的问题
有人能给我推荐什么吗?它需要超级精确和快速。最好不要基于内存,因为我只有32gb的ram可供使用。我不是这类算法的专家,但如果它是文本数据(或数字,无所谓),您可以尝试读取您的大文件,并通过前两个或三个符号将其写入多个文件:所有以“aaa”开头的行转到aaa.txt,所有以“aab”开头的行-到aab.txt等。您将获得许多文件,其中数据处于等价关系:单词的副本与单词本身位于同一文件中。现在,只要解析内存中的每个文件,就完成了。
同样,我也不确定它是否有效,但我会先尝试这种方法…删除重复项的标准方法是对文件进行排序,然后按顺序传递以删除重复项。对5亿行进行排序并不是一件小事,但肯定是可行的。几年前,我有一个每日进程,可以在16GB的机器上对50到100GB的数据进行排序 顺便说一句,你也许可以用现成的程序来实现这一点。当然,GNU排序实用程序可以对大于内存的文件进行排序。我从未在500 GB的文件上尝试过,但你可以试一试。您可以将其与本教程的其余部分一起下载。该实用程序有一个
--unique
选项,因此您应该能够对--unique输入文件>输出文件进行排序。它使用了一种类似于我下面描述的技术。我建议先在一个100兆字节的文件上试一下,然后慢慢升级到更大的文件
使用GNU排序和我在下面介绍的技术,如果输入目录和临时目录位于不同的物理磁盘上,它的性能会更好。将输出放在第三个物理磁盘上,或与输入放在同一个物理磁盘上。您希望尽可能减少I/O争用
也可能有一个商业(即支付)程序来进行排序。开发一个能够有效地对一个巨大的文本文件进行排序的程序是一项非常重要的任务。如果你能花几百美元买一件东西,如果你的时间值得的话,你可能会提前付钱
如果你不能使用现成的程序,那么
如果文本位于多个较小的文件中,则问题更容易解决。首先对每个文件进行排序,从这些文件中删除重复项,然后写入已排序的临时文件,删除重复项。然后运行一个简单的n-way合并,将这些文件合并到一个已删除重复项的输出文件中
如果您只有一个文件,那么首先要将尽可能多的行读入内存,对这些行进行排序,删除重复项,然后编写一个临时文件。在整个大文件中继续这样做。完成后,您可以合并一些已排序的临时文件
在伪代码中,它看起来像这样:
fileNumber = 0
while not end-of-input
load as many lines as you can into a list
sort the list
filename = "file"+fileNumber
write sorted list to filename, optionally removing duplicates
fileNumber = fileNumber + 1
您实际上不必从临时文件中删除重复项,但如果您的唯一数据实际上仅占总数的10%,则不将重复项输出到临时文件将节省大量时间
写入所有临时文件后,需要合并它们。根据您的描述,我估计您从文件中读取的每个块将包含大约2000万行。因此,您可能需要处理25个临时文件
您现在需要执行一个k-way合并。这是通过创建优先级队列来完成的。打开每个文件,从每个文件中读取第一行,并将其与来自该文件的引用一起放入队列。然后,从队列中取出最小的项并将其写入输出文件。要删除重复项,请跟踪输出的上一行,如果新行与上一行相同,则不输出新行
输出该行后,从刚输出的文件中读取下一行,并将该行添加到优先级队列。继续此操作,直到清空所有文件
前一段时间我发表了一系列文章。它使用了我上面描述的技术。它唯一没有做的就是删除重复项,但这只是对输出临时文件的方法和最终输出方法的简单修改。即使没有优化,该程序也可以运行得很好。它不会设置任何速度记录,但它应该能够在不到12小时内从5亿行中排序和删除重复项。考虑到第二个过程只处理总数据的一小部分(因为您从临时文件中删除了重复项),可能要少得多
你可以做一件事来加快程序的运行速度,那就是操作较小的块,并在后台线程中对一个块进行排序,同时将下一个块加载到内存中。你最终不得不处理更多的临时文件,但这真的不是问题。堆操作稍微慢一点,但通过将输入和输出与排序重叠,额外的时间会被重新捕获。你最终得到的I/O基本上是免费的。在