如何将预先排序的文件合并为单个大文件,而不使用过多的内存或临时磁盘

如何将预先排序的文件合并为单个大文件,而不使用过多的内存或临时磁盘

我正在尝试对 1.4TB 文件进行排序(最好是删除重复行)。

分割和排序各个块不是问题,但重新组装它们却是一个挑战。我从手册页中期望“sort -m”(在 FreeBSD 11 下)会进行简单的合并,创建一个聚合的完美排序的输出,可以选择使用 -u 选项抑制重复项。

但在让它运行一段时间后,我发现 sort(到目前为止)已经生成了数百个临时文件,就像它像平常一样对输入进行排序一样。

我没有足够的磁盘空间来存储相同的数据 3 次。是否有任何实用程序可以对已排序的文件进行简单合并,而不需要临时磁盘空间?

===结果===

我最终使用了“标准”排序。处理过程需要大约 50 个小时的高 CPU 和磁盘负载,其中包括生成数百个临时文件。尽管输入已经被完美排序,但还是如此。我仍然有兴趣了解是否有一个简单的实用程序可以整齐地合并预先排序的文件。

答案1

今天用不同的数据做了一些更多的实验,我相信我可能已经发现了问题:默认情况下,sort(BSD)一次只会打开16个文件(手册页似乎暗示这包括输入文件和临时文件)。

--batch-size= 开关将允许增加此计数。

使用大小为 100MB 的预排序文件:

  1. sort -u -m <...15 个文件名...>

    • 立即输出
  2. sort -u -m <...16 个文件名...>

    • 似乎以至少两个单独的块处理输入,包括临时文件的中间使用
  3. 种类--批量大小=20-u -m <...16 个文件名...>

    • 立即输出

请注意,我无法在原始数据上对此进行测试,但我相当确定这就是问题所在。

希望这可以帮助遇到同样问题的人。

答案2

您的要求(因此备用内存/存储/云)将使速度变得非常慢,但可以通过编写自己的文件系统驱动程序来实现。但是,如果您有时间/技能来做到这一点,那么租用/购买/出售/退回 37 美元的 2TB 驱动器并使用会更快/更便宜

https://en.m.wikipedia.org/wiki/External_sorting

如果文件可压缩,解决方法可能是 zram 和/或 7z/fs 压缩,您可以为第二个副本腾出空间

https://en.m.wikipedia.org/wiki/Zram

https://en.m.wikipedia.org/wiki/Category:压缩文件系统

如果有空间用于输出而不删除输入并且输入已预先排序,那么它是微不足道的。

答案3

我在尝试解决一个非常大的滑块难题时遇到了类似的问题。目前我必须合并大约 100 个已排序的文件,每个文件包含大约 6000 万个位置,占用 15 GB。文件单独排序,不重复,但不同文件可以有相同的记录。

我用 C++ 编写了一个实用程序,它基本上打开所有文件并一次从每个文件中读取一条记录。在每一步中,它都会找到按字母顺序排列最早的记录(使用 SHELL 排序)并写入该记录。它从该文件以及也具有相同记录的任何其他文件中读取下一条记录。为了得到答案,它在一台新的 MAC 笔记本电脑上运行了 5 个小时。

内存要求不大,每个文件只读取一次。它的运行速度比通信解决方案快得多,通信解决方案一次仅限于两个文件,并且涉及文件的多次读取。

该程序已在两台计算机上编译并运行:最初开发该程序的 MAC 笔记本电脑和 MAC M1。迄今为止运行的最大作业有 676 个文件,每个文件约有 6000 万条记录或大小 1.5 GB,运行时间略多于 10 个小时。

源代码:布鲁塞莫斯/梳子

答案4

我想你正在寻找的是comm。我不确定它使用了多少内存或临时空间,但考虑到输入文件已排序的要求以及编写这些实用程序的人并不愚蠢,我敢打赌它确实非常高效。

您可以使用 删除重复项,uniq因为这也假设输入已排序。

https://www.tutorialspoint.com/unix_commands/comm.htm

相关内容