UNIXのsortコマンドは、非常に大きなファイルをどのようにソートできますか?


104

UNIX sortコマンドは、次のように非常に大きなファイルをソートできます。

sort large_file

並べ替えアルゴリズムはどのように実装されていますか?

それはなぜメモリの過度の消費を引き起こさないのですか?


これは面白い。私はそれがどのように機能するのか本当にわかりませんが、私は推測しています。おそらく、各キーの最初の文字をバイナリツリーに入れ、衝突が発生すると、キーの次の文字も使用するため、必要以上にキーを保存することはありません。次に、各キーとともにファイルにオフセットを保存して、各行を順番にシークして印刷できるようにします。
Zifre 2009年

実際、@ ayazは、ディスク上のファイルを並べ替えるのではなく、パイプ内で並べ替えるほうが興味深いです。入力データに対して複数のパスを単純に実行できないことが明らかだからです。
tvanfosson

3
なぜSOの誰もが常に推測することを余儀なくされているのですか?

入力に対して複数のパスを実行できます。すべての入力を読み取り、それをディスクに書き込んでから、ディスクファイルを並べ替えるだけです。

2
@ニール-コンテキストから、彼がファイル名ではなくファイルのコンテンツをソートしようとしていることは明らかであるように見えました(1つの名前では意味がありません)。単純な間違いで反対票ではなく回答が得られるように、コンテキストをあまり変更せずに質問を改善したかっただけです。
tvanfosson 09年

回答:



42

このsortコマンドは、作業データを一時ディスクファイル(通常は/tmp)に保存します。


20
-T一時ディレクトリの指定に使用
glenn jackman '22

12

警告:このスクリプトはチャンクごとに1つのシェルを開始します。非常に大きなファイルの場合、これは数百になる場合があります。


これは私がこの目的のために書いたスクリプトです。4プロセッサマシンでは、ソートパフォーマンスが100%向上しました。

#! /bin/ksh

MAX_LINES_PER_CHUNK=1000000
ORIGINAL_FILE=$1
SORTED_FILE=$2
CHUNK_FILE_PREFIX=$ORIGINAL_FILE.split.
SORTED_CHUNK_FILES=$CHUNK_FILE_PREFIX*.sorted

usage ()
{
     echo Parallel sort
     echo usage: psort file1 file2
     echo Sorts text file file1 and stores the output in file2
     echo Note: file1 will be split in chunks up to $MAX_LINES_PER_CHUNK lines
     echo  and each chunk will be sorted in parallel
}

# test if we have two arguments on the command line
if [ $# != 2 ]
then
    usage
    exit
fi

#Cleanup any lefover files
rm -f $SORTED_CHUNK_FILES > /dev/null
rm -f $CHUNK_FILE_PREFIX* > /dev/null
rm -f $SORTED_FILE

#Splitting $ORIGINAL_FILE into chunks ...
split -l $MAX_LINES_PER_CHUNK $ORIGINAL_FILE $CHUNK_FILE_PREFIX

for file in $CHUNK_FILE_PREFIX*
do
    sort $file > $file.sorted &
done
wait

#Merging chunks to $SORTED_FILE ...
sort -m $SORTED_CHUNK_FILES > $SORTED_FILE

#Cleanup any lefover files
rm -f $SORTED_CHUNK_FILES > /dev/null
rm -f $CHUNK_FILE_PREFIX* > /dev/null

参照:「シェルスクリプトを使用して大きなファイルをより速くソートする


35
GNUソートバージョン8.11以降、sort --parallel Nを使用するだけです
jhclark

5
GNU coreutils 8.6は実際に
bdeonovic '17 / 10/17

1
これは私のためのトリックをしました。私はソート8.4バージョンを持っています。ファイル(1億9千万行)で直接sortを使用しても、どこにも行きません。このプログラムは4分弱
Sunil B

繰り返しますが、この回答は質問とは何の関係もありません
WattsInABox '28

2
このスクリプトは危険です。私のLinuxマシンは、何百ものソートプロセスを起動した後、応答を失いました…
Yongwei Wu


11
#!/bin/bash

usage ()
{
    echo Parallel sort
    echo usage: psort file1 file2
    echo Sorts text file file1 and stores the output in file2
}

# test if we have two arguments on the command line
if [ $# != 2 ]
then
    usage
    exit
fi

pv $1 | parallel --pipe --files sort -S512M | parallel -Xj1 sort -S1024M -m {} ';' rm {} > $2

これは素晴らしいです。並列パッケージがあることを知らなかった!上記を使用した後、ソート時間は50%以上改善されました。ありがとう。
xbsd 2013

これで生成されたファイルのdiffにcommを使用しようとすると、ファイルがソートされていないという警告が表示されます。
ashishb 2014年

7

ソートのオプションを注意深く見てパフォーマンスを向上させ、マシンと問題への影響を理解してください。Ubuntuの主要なパラメーターは

  • 一時ファイルの場所-T directory_name
  • 使用するメモリの量-SN%(使用するすべてのメモリのN%であるほど、ディスクへのスワッピングの原因となるオーバーサブスクリプションを回避できます。 "-S 80%"のように使用すると、使用可能なRAMの80%を使用できます。または "-S 2G"(2 GB RAM)。)

質問者は「メモリ使用量が多いのはなぜですか?」その答えは歴史から来ています。古いUNIXマシンは小さく、デフォルトのメモリサイズは小さく設定されています。これをワークロードに合わせてできるだけ大きく調整して、ソートのパフォーマンスを大幅に向上させます。作業ディレクトリを、ソートするファイルのサイズの少なくとも1.25 *を保持するのに十分なスペースがある最速のデバイスの場所に設定します。


これを2.5GBファイル、64GBのRAMが搭載されたボックスで-S 80%で試してみると、ファイル全体がそれよりも小さくても、実際にはその完全なパーセンテージが使用されています。何故ですか?それは根拠のないと思われるインプレースの並べ替えを使用していない場合でも
ジョセフ・ガービン

おそらくsort -Sは、ファイルの内容を読み取る前に、ソートプロセス用のメモリを事前に割り当てます。
Fred Gannett

-3

メモリは問題ではないはずです-ソートはすでにそれを処理しています。マルチコアCPUを最適に使用したい場合は、これを小さなスクリプトで実装します(ネットで見られるものと似ていますが、それらのほとんどよりも単純/クリーンです;))。

#!/bin/bash
# Usage: psort filename <chunksize> <threads>
# In this example a the file largefile is split into chunks of 20 MB.
# The part are sorted in 4 simultaneous threads before getting merged.
# 
# psort largefile.txt 20m 4    
#
# by h.p.
split -b $2 $1 $1.part
suffix=sorttemp.`date +%s`
nthreads=$3
i=0
for fname in `ls *$1.part*`
do
    let i++
    sort $fname > $fname.$suffix &
    mres=$(($i % $nthreads))
    test "$mres" -eq 0 && wait
done
wait
sort -m *.$suffix 
rm $1.part*

4
興味深いスクリプトですが、この質問に答えることはできません。
Joachim Sauer、2011

5
split -bはバイトで分割するため、任意の位置で行を切り捨てます
ithkuil
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.