我有一个非常大的文件,超过100GB(数十亿行),我想在内存有限的unix系统上尽快进行两级排序。这将是大型 Perl 脚本中的一个步骤,因此如果可能的话我想使用 Perl。
那么,我该怎么做呢?我的数据如下所示:
A 129
B 192
A 388
D 148
D 911
A 117
...但是对于数十亿行。我需要先按字母排序,然后按数字排序。使用unix排序会更容易吗,比如......
sort -k1,2 myfile
或者我可以用 Perl 来完成这一切吗?我的系统有 16GB 内存,但文件大约有 100GB。
感谢您的建议!
UNIX
sort
实用程序可以通过在磁盘空间上创建临时工作文件来处理对大数据(例如大于您的工作 16GB RAM)的排序。
因此,我建议按照您的建议简单地使用 UNIX
sort
,调用选项 -T tmp_dir
,并确保 tmp_dir
有足够的磁盘空间来容纳所有将要使用的临时工作文件。在那里创建的。
顺便说一句,这在之前的SO问题中进行了讨论。
UNIX
sort
是对这种规模的数据进行排序的最佳选择。我建议使用快速压缩算法LZO
。它通常分布为lzop
。使用 -S
选项设置大排序缓冲区。如果您的磁盘比默认的 /tmp
设置更快,也设置 -T
。另外,如果您想按数字排序,则必须将排序数字排序定义为第二个排序字段。因此,您应该使用这样的行以获得最佳性能:
LC_ALL=C sort -S 90% --compress-program=lzop -k1,1 -k2n
我有完全相同的问题! 经过大量搜索后,由于我不希望对 shell (UNIX) 有任何依赖以使其在 Windows 上可移植,所以我想出了以下解决方案:
#!/usr/bin/perl
use File::Sort qw(sort_file);
my $src_dic_name = 'C:\STORAGE\PERSONAL\PROJECTS\perl\test.txt';
sort_file({k => 1, t=>" ", I => $src_dic_name, o => $src_dic_name.".sorted"});
我知道这是一篇旧帖子,但用解决方案更新它,以便很容易找到。
正如 Hynek 已经说过的,gnu-sort 非常擅长处理大量数据,他们甚至使用几种不同的算法来预排序较小的块,然后用另一种算法将它们重新组合。
但是您可以使用 -S 内存选项使其变得更好。默认情况下,gnu-sort 最多使用大约 4-8MByte 的内存 - 来自 1990 年代的美好问候。
在我的 64GByte 机器上,我必须对 300GByte 文件进行排序。使用 -S 16G 将速度提高了 20 倍,并减少了大约 60-80% 的写入访问,如果您想减少闪存上的写入负载,这非常好。
只有一个缺点,至少在我的 64GByte-Cygwin-System 上,任何高于 16GByte 的东西都会产生不稳定的结果 - 突然内存不足、挂起、变得非常慢等等。这可能是 Windows 的问题,因为即使某些 Windows 软件也无法使用整个内存(我尝试使用 48GByte 字典进行 xz,但超过 32GByte 的所有内容也不可靠)。