UNIX sıralama komutu çok büyük bir dosyayı nasıl sıralayabilir?


104

UNIX sortkomutu çok büyük bir dosyayı şöyle sıralayabilir:

sort large_file

Sıralama algoritması nasıl uygulanır?

Neden aşırı hafıza tüketimine neden olmuyor?


Bu ilginç. Nasıl çalıştığını gerçekten bilmiyorum ama bir tahminim var. Muhtemelen her anahtarın ilk karakterini bir ikili ağaca koyar ve bir çarpışma olduğunda, anahtarın bir sonraki karakterini de kullanır, böylece anahtarın gerekenden fazlasını kaydetmez. Daha sonra her tuşla dosyaya bir ofset kaydedebilir, böylece her satırı geri arayabilir ve sırayla yazdırabilir.
Zifre

Aslında, @ayaz, bir dosyayı diskte değil de bir kanalda sıralıyorsanız daha ilginçtir, çünkü bu, girdi verileri üzerinden birden fazla geçiş yapamayacağınızı açıkça ortaya koyar.
tvanfosson

3
Neden SO'daki herkes her zaman tahmin etme isteği duyuyor?

Girişte birden çok geçiş yapabilirsiniz - yalnızca tüm girişi okumanız, diske yazmanız ve ardından disk dosyasını sıralamanız gerekir.

2
@Neil - bağlamdan, dosya adını değil (bir isim için anlamsız olan) dosyanın içeriğini sıralamaya çalıştığı açık görünüyordu. Sadece bağlamı çok fazla değiştirmeden soruyu iyileştirmek istedim, böylece basit bir hata nedeniyle olumsuz oylar yerine yanıtlar alacaktı.
tvanfosson

Yanıtlar:


111

UNIX sırala komutunun Algoritmik ayrıntıları Unix sırala Harici R-Way birleştirme sıralama algoritması kullanır diyor. Bağlantı daha fazla ayrıntıya giriyor, ancak özünde girdiyi daha küçük bölümlere (belleğe sığan) böler ve ardından her bölümü sonunda birleştirir.



12

UYARI: Bu komut dosyası yığın başına bir kabuk başlatır, gerçekten büyük dosyalar için bu yüzlerce olabilir.


İşte bu amaçla yazdığım bir senaryo. 4 işlemcili bir makinede sıralama performansını% 100 artırdı!

#! /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

Ayrıca bkz .: " Büyük dosyaları bir kabuk komut dosyasıyla daha hızlı sıralama "


35
GNU sıralama sürümü 8.11'den itibaren sort --parallel N kullanabilirsiniz
jhclark

5
GNU coreutils 8.6 aslında
bdeonovic

1
Bu benim için hile yaptı. Sınıf 8.4 sürümüne sahibim. Sıralamayı doğrudan dosya üzerinde (190 milyon satır) kullanmak hiçbir yere gitmiyordu. Bu program 4 dakikanın biraz altında gerçekleştirdi
Sunil B

Yine, bu cevabın soruyla hiçbir ilgisi yok
WattsInABox

2
Bu senaryo tehlikelidir. Linux makinem, yüzlerce sıralama sürecini başlattıktan sonra yanıtını kaybetti…
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

Bu mükemmel. Paralel bir paket olduğunun farkında değildim! Yukarıdakileri kullandıktan sonra sıralama süresi% 50'den fazla iyileştirildi. Teşekkürler.
xbsd

Bunun oluşturduğu dosyalarda diff için comm kullanmayı denedim ve bu bana dosyaların sıralanmadığı konusunda uyarı veriyor.
ashishb

7

Performansı hızlandırmak için sıralama seçeneklerine dikkatlice bakın ve bunun makineniz ve probleminiz üzerindeki etkisini anlayın. Ubuntu'daki temel parametreler

  • Geçici dosyaların konumu -T dizin_adı
  • Kullanılacak bellek miktarı -SN% (Kullanılacak tüm belleğin% N kadarı, daha iyidir, ancak diske geçişe neden olan aşırı abonelikten kaçının. Kullanılabilir RAM'in% 80'ini kullanmak için "-S% 80" gibi kullanabilirsiniz, veya 2 GB RAM için "-S 2G".)

Soru soran kişi "Neden yüksek bellek kullanımı yok?" Bunun cevabı geçmişten geliyor, eski unix makineleri küçüktü ve varsayılan bellek boyutu küçük ayarlandı. İş yükünüzün sıralama performansını büyük ölçüde iyileştirmesi için bunu mümkün olduğunca büyük ayarlayın. Çalışma dizinini, en hızlı cihazınızda, sıralanan dosyanın en az 1,25 * boyutunu tutacak kadar yeterli alana sahip bir yere ayarlayın.


Bunu 2.5GB'lık bir dosyada, 64GB RAM'li bir kutuda -S 80% ile denerken, aslında dosyanın tamamı bundan daha küçük olsa bile tam yüzdeyi kullanıyor. Neden? gereksiz görünen yerinde sıralama kullanmasa bile
Joseph Garvin

Muhtemelen sırala -S, dosyanın içeriğini okumadan önce, sıralama işlemi için belleği önceden ayırır.
Fred Gannett

-3

Hafıza bir sorun olmamalı - sıralama bunu halihazırda halleder. Çok çekirdekli CPU'nuzu en iyi şekilde kullanmak istiyorsanız, bunu küçük bir betikte uyguladım (ağda bulabileceğiniz bazılarına benzer, ancak bunların çoğundan daha basit / daha temiz;)).

#!/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
İlginç bir senaryo, ancak bu soruyu yanıtlamak için hiçbir şey yapmıyor.
Joachim Sauer

5
split -b, baytlara göre böler, böylece satırları rastgele bir konumda
keser
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.