如何对大文件进行排序?

eva*_*ine 43 sort

我有一台配备 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 处理这么大的文件?

Gra*_*eme 64

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

'--平行=n'

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

由于您的 CPU 有 2 个内核,您可以执行以下操作:

sort --parallel=2 -uo list-sorted.txt list.txt
Run Code Online (Sandbox Code Playgroud)

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

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

nice -n -20 ionice -c2 -n7 sort --parallel=2 -uo list-sorted.txt list.txt
Run Code Online (Sandbox Code Playgroud)

另请注意,正如Gilles评论的那样,使用单个 GNU 排序命令将比分解排序的任何其他方法更快,因为该算法已经针对处理大文件进行了优化。其他任何事情都可能只会减慢速度。

  • 并且您应该注意到,直接调用 `sort` 比您可以拼凑的任何其他东西都要好。GNU sort 旨在很好地处理比 RAM 大得多的文件。 (11认同)
  • 另请参阅 https://superuser.com/questions/938558/sort-parallel-isnt-parallelizing – 如果您注意到它实际上并未并行化,则可能需要指定类似 -S512M 的内容。 (3认同)

Sté*_*las 54

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

但是您可能希望将语言环境修复为 C。

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

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

所以:

LC_ALL=C sort -u file
Run Code Online (Sandbox Code Playgroud)

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

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


现在只是给那些反对(在某种程度上是正确的)的人注意,这不是正确的顺序

我同意作为一个人,我希望看到Stéphane介于StefanStephanie之间,但是:

  • 计算机希望斯特凡因为后进行排序é(至少当作为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
      
      Run Code Online (Sandbox Code Playgroud)
    • 但 ?, ?, ?所有排序相同(显然这些语言环境定义中的错误¹):

      $ printf '%s\n' ? ? ? | sort -u
      ?
      
      Run Code Online (Sandbox Code Playgroud)

      在这里,它是?,但它也可以是?或者 ?

所以 IMO,sort -u如果你想要独特的线条,你可能总是想要LC_ALL=C。如果您希望按照用户的排序顺序对结果列表进行排序,请sort再次将其通过管道传输到:

LC_ALL=C sort -u | sort

LC_ALL=C sort | LC_ALL=C uniq -c | sort -k2
Run Code Online (Sandbox Code Playgroud)

¹ 2019 年编辑。的顺序 ?? ? ? ?... 已经在较新版本的 GNU libc 中得到修复,但截至 2.30,超过 95% 的字符仍然没有定义的顺序,您可以替换 ? ? ? ? ? 例如。希望 GNU 语言环境最终将被完全修复(如果他们想遵守标准的下一个修订版,他们将不得不这样做),然后问题将仅限于用户定义的语言环境

  • +1 用于设置语言环境:它可以对性能产生巨大影响 (8认同)