web-dev-qa-db-ja.com

大きなファイルを並べ替える方法は?

Intel(R)Pentium(R)CPU G640 @ 2.80 GHzと8 GBのRAMを搭載したPCを持っています。私はその上でEXT3ファイルシステムを備えたScientific Linux 6.5を実行しています。

このセットアップで、私ができる最も速い方法は何ですかsort -u 200ギガバイトのファイル?

ファイルを小さいファイル(8 GB未満)に分割する必要がある場合、sort -uそれらをまとめ、それらを再度別のサイズに分割しますsort -u再び、など?または、並べ替えスクリプト、限られた量のRAMでこれほど大きなファイルを処理できるプログラムはありますか?

37
evachristine

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

プロセッサの hyper-threading があるため、実際のコア数を指定することをお勧めします。

Niceを試してプロセッサのスケジューリング優先度に影響を与えたり、ioniceを試してI/Oスケジューリングに影響を与えることもできます。このような他のプロセスよりも優先度を上げることができますが、バックグラウンドプロセスがを使いすぎないようにするための通常の方が優れているため、大幅な節約になるとは思いませんリソース。それにもかかわらず、それらを次のようなものと組み合わせることができます。

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

Gilles がコメント化されているため、単一のGNU sortコマンドを使用すると、他のソート方法よりも高速になります。他の何かはおそらくただ物事を遅くします。

49
Graeme

sortコマンドを使用するのがおそらく最速のオプションです。

しかし、おそらくロケールをCに修正する必要があります。

sort -uは一意の行を報告しませんが、同じようにソートする各行のセットの1つ。 Cロケールでは、2つの異なる行は必ずしも同じようにソートされませんが、GNUシステム上のほとんどのUTF-8ベースのロケールではそうではありません。

また、Cロケールを使用すると、UTF-8を解析して複雑なソート順を処理するオーバーヘッドが回避されるため、パフォーマンスが劇的に向上します。

そう:

LC_ALL=C sort -u file

-Tまたは$TMPDIR環境変数を使用して)一時ファイルに高速ドライブ(または入力ファイルや出力ファイルがあるドライブとは別のドライブ)を使用してパフォーマンスを向上させることもできます。一部のsort実装でサポートされている-Sオプションをいじることによって)。

一部のタイプの入力または低速のストレージでは、GNU sort--compress-programオプションを使用すると(たとえば、lzopを使用)、ストレージ使用量に加えて。


さて、それは正しい順序ではない

私は人間として、StéphaneStefanStephanieの間でソートされることを望んでいることに同意しますが、

  • computerStéphaneé以降(少なくともU + 00E9として表される場合)の文字またはそのバイトとしてソートしたいUTF-8エンコーディングは、(コードポイントまたはバイト値に関して)後にソートされます。これは、実装が非常に簡単なソート順であり、 strict total order であり、驚きはありません。
  • ロケールのソート順は、多くの場合、人間にとっても満足のいくものではありません。たとえば、デフォルトのen_GB.utf8ロケールを使用するシステムでは、次のようになります。

    • StéphaneおよびStéphane(一方はU + 00E9、もう一方はeU + 0301)は同じソートを行いません。

      $ printf '%b\n' 'Ste\u0301phane' 'St\u00e9phane' | sort -u
      Stéphane
      Stéphane
      
    • しかし、③、①、②はすべて同じようにソートします(明らかにこれらのロケール定義のバグa):

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

      ここでは③ですが、①でも②でもかまいません。

したがって、IMO、一意の行が必要な場合は、LC_ALL = Cを指定したsort -uが常に必要になる可能性があります。そして、その結果のリストをユーザーのソート順でソートしたい場合は、もう一度sortにパイプします。

LC_ALL=C sort -u | sort

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

¹2019編集。 ①②③④⑤...の順序は、GNU libcの新しいバージョンで修正されていますが、2.30以降、95%以上の文字に定義された順序がありません。 、たとえば、①②③④⑤を???? ???? ???? ???? ????に置き換えることができます。うまくいけば、GNUロケールは最終的に修正されます完全に( 彼らが標準の次のリビジョンに準拠したい場合、彼らはそうする必要があります )そして問題はユーザー定義のロケールに限定されます

47