如何排序大文件?


35

我有一台装有Intel(R)Pentium(R)CPU G640 @ 2.80 GHz和8 GB RAM的PC。我正在使用EXT3文件系统在其上运行Scientific Linux 6.5。

在这种设置下,sort -u对200 GB的文件进行刻录的最快方法是什么?

我是否应该将文件拆分为较小的文件(小于8 GB)sort -u,将它们放在一起,然后再次以不同的大小拆分sort -u,等等?还是有任何排序脚本,程序可以用有限的RAM来处理这么大的文件?


6
编辑您的问题,并解释当您尝试发布的命令时会发生什么。磁盘空间用完了吗?只要您的计算机上有足够的可用空间,该命令就应该起作用/tmp
terdon


1
所选择的答案基本上是说什么@terdon是说,也看看这个- stackoverflow.com/a/13025731/2801913parallel我认为您将需要GNU ,而不是parallel某些系统上默认安装的moreutils 。
Graeme 2014年

1
您可以将文件上传到Amazon S3,然后启动带有几百个节点的Elastic Map Reduce作业以对其进行排序!
艾伦·舒特科

2
sort(1)可能耗尽空间/tmp; 如果是这样,您可以使用环境变量TMPDIR或标志为临时文件指定另一个区域-T=<tmpdir>
vonbrand 2014年

Answers:


46

GNU sort(在大多数Linux系统上是默认值)具有一个--parallel选项。从http://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html中

'--parallel = n'

将并行运行的排序数设置为n。默认情况下,将n设置为可用处理器的数量,但将其限制为8,因为此后性能提升将逐渐降低。还要注意,使用n个线程会使内存使用量增加log n。另请参见nproc调用。

由于您的cpu有2个核心,因此您可以执行以下操作:

sort --parallel=2 -uo list-sorted.txt list.txt

最好指定实际的内核数,因为处理器具有超线程功能,因此内核数可能会更多。

您还可以尝试nice影响处理器调度优先级并ionice影响I / O调度。您可以像这样增加其他进程的优先级,我认为这不会为您节省很多,因为它们通常可以更好地确保后台进程不使用过多的资源。不过,您可以将它们与以下内容结合使用:

nice -n -20 ionice -c2 -n7 sort --parallel=2 -uo list-sorted.txt list.txt

还要注意的是,正如Gilles所评论的那样,使用单个GNU排序命令比任何其他分解排序的方法都快,因为该算法已经过优化,可以处理大文件。其他任何事情都可能只会减慢速度。


10
您应该注意,sort直接拨打电话比您能解决的其他任何事情都要好。GNU sort设计用于很好地处理比RAM大得多的文件。
吉尔(Gilles)'所以

--parallel sort选项在我的RH6.5服务器上不起作用。Sort --version认为它来自coreutils 8.4。与并行版本相比,我需要哪个版本?
markus_b 2015年

3
另请参见superuser.com/questions/938558/sort-parallel-isnt-parallelizing –如果您注意到它实际上不是并行化的,则可能必须指定-S512M之类的名称。
2015年

46

使用该sort命令可能是最快的选择。

但是您可能想要将语言环境固定为C。

sort -u不会报告唯一行,但会报告一组排序相同的行。在C语言环境中,两条不同的行不一定会排序相同,但是在GNU系统上大多数基于UTF-8的语言环境中,情况并非如此。

而且,使用C语言环境避免了必须解析UTF-8和处理复杂的排序顺序的开销,因此可以显着提高性能。

所以:

LC_ALL=C sort -u file

您还可以通过使用更快的驱动器(或与输入和/或输出文件所在的驱动器不同的驱动器)作为临时文件(使用-T$TMPDIR环境变量),或摆弄-S某些sort实现支持的选项来提高性能。。

对于某些类型的输入或用于慢速存储,使用--compress-programGNU选项sort(例如与一起使用lzop)可能会提高存储使用性能。


现在只是对那些反对(一定程度上)反对的人的说明,它不是正确的顺序

我同意,作为一个人类,我希望看到StéphaneStefanStephanie之间进行排序,但是:

  • 计算机希望斯特凡因为后进行排序é(至少当作为U + 00E9表示),为字符或者其UTF-8编码的排序后的字节(码点或字节值而言)。这是一个很容易实现的排序顺序,并且是严格的总顺序,也就不足为奇了。
  • 在许多情况下,即使对于人类,您的语言环境的排序顺序也可能无法令人满意。例如,在我的系统上使用默认的en_GB.utf8语言环境:

    • StéphaneStéphane(一个使用U + 00E9,另一个使用eU + 0301)的排序不同:

      $ printf '%b\n' 'Ste\u0301phane' 'St\u00e9phane' | sort -u
      Stéphane
      Stéphane
      
    • 但是③,①,②都排序相同(显然是那些语言环境定义中的错误):

      $ printf '%s\n' ③ ① ② | sort -u
      ③
      

      在这里是③,但也可能是①或②

因此,IMO,sort -u如果您想要唯一的行,那么您总是希望LC_ALL = C。而且,如果您希望按照用户的排序顺序对结果列表进行排序,请sort再次将其传递给:

LC_ALL=C sort -u | sort

LC_ALL=C sort | LC_ALL=C uniq -c | sort -k2

8
+1设置区域设置:可能会对性能产生巨大影响
Adrian Pronk 2014年

1
是。250000行的排序文件LC_ALL可以使速度加快8倍。
Jan Vlcinsky '18

-1

这是一个随时可用的bash脚本,用于在具有GB GB内存的常规计算机上对TB规模数据进行排序:http : //sgolconda.blogspot.com/2015/11/sort-very-large-dataset.html 它会检查将您的计算机作为核心,并使用所有核心。可以排序,数字或字符串文件。可用于在TB规模数据中查找唯一记录。


这不是一个好建议。该脚本非常肿,将输入文件拆分为GNU sort不需要的已接受答案指出的部分。
托尔比约恩Ravn的安徒生
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.