Jak sortować duże pliki?


35

Mam komputer z procesorem Intel® Pentium® G640 @ 2,80 GHz i 8 GB pamięci RAM. Używam na nim Scientific Linux 6.5 z systemem plików EXT3.

W tej konfiguracji, jaki jest najszybszy sposób sort -una wykonanie pliku o pojemności 200 gigabajtów?

Czy powinienem podzielić plik na mniejsze pliki (mniejsze niż 8 GB), sort -uzłożyć je razem, a następnie ponownie podzielić na inny rozmiar sort -uitp.? A może istnieją jakieś skrypty sortujące, programy, które mogłyby obsługiwać tak duże pliki przy mojej ograniczonej ilości pamięci RAM?


6
Proszę edytować swoje pytanie i wyjaśnić, co dzieje się podczas próby polecenie, które pisał. Czy zabrakło Ci miejsca na dysku? Polecenie powinno działać, o ile masz wystarczająco dużo wolnego miejsca /tmp.
terdon


1
Wybrana odpowiedź w zasadzie mówi, co mówi @terdon, ale także sprawdź tę - stackoverflow.com/a/13025731/2801913 . parallelMyślę, że będziesz potrzebować GNU do tego, a nie moreutils, parallelktóry jest domyślnie instalowany w niektórych systemach.
Graeme

1
Możesz przesłać plik do Amazon S3, a następnie rozpiąć elastyczną mapę Zmniejsz zadanie z kilkuset węzłami, aby go posortować!
Alan Shutko

2
sort(1)może zabraknąć miejsca na /tmp; jeśli tak, możesz wyznaczyć inny obszar dla plików tymczasowych ze zmienną środowiskową TMPDIRlub flagą-T=<tmpdir>
vonbrand

Odpowiedzi:


46

GNU sort(który jest domyślny w większości systemów Linux), ma --parallelopcję. From http://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html :

„--parallel = n”

Ustaw liczbę sortowań uruchamianych równolegle na n. Domyślnie n jest ustawione na liczbę dostępnych procesorów, ale jest ograniczone do 8, ponieważ po tym następuje spadek wydajności. Zauważ też, że użycie n wątków zwiększa użycie pamięci przez współczynnik n. Zobacz także wywołanie nproc.

Ponieważ twój procesor ma 2 rdzenie, możesz:

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

Lepiej jest podać rzeczywistą liczbę rdzeni, ponieważ może się wydawać, że jest ich więcej, ponieważ procesor ma hiperwątkowość .

Możesz także eksperymentować z nicewpływaniem na priorytet szeregowania procesora i ionicena harmonogram we / wy. Możesz zwiększyć priorytet w stosunku do innych procesów takich jak ten, nie sądzę, aby to przyniosło duże oszczędności, ponieważ zwykle są one lepsze, aby proces w tle nie zużywał zbyt wielu zasobów. Niemniej jednak możesz połączyć je z czymś takim jak:

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

Zauważ też, że jak skomentował Gilles , użycie pojedynczego polecenia sortowania GNU będzie szybsze niż jakakolwiek inna metoda podziału sortowania, ponieważ algorytm jest już zoptymalizowany do obsługi dużych plików. Wszystko inne prawdopodobnie tylko spowolni sytuację.


10
I powinieneś pamiętać, że sortbezpośrednie dzwonienie jest lepsze niż cokolwiek innego, co możesz sobie wyobrazić. Sortowanie GNU jest zaprojektowane tak, aby dobrze radzić sobie z plikami, które są znacznie większe niż RAM.
Gilles „SO- przestań być zły”

Opcja sortowania równoległego nie działa na moich serwerach RH6.5. Sortuj - wersja myśli, że pochodzi z coreutils 8.4. Jakiej wersji potrzebuję do wersji równoległej?
markus_b

3
Zobacz także superuser.com/questions/938558/sort-parallel-isnt-parallelizing - może być konieczne określenie czegoś takiego jak -S512M, jeśli zauważysz, że tak naprawdę nie jest on równoległy.
młot

46

Użycie sortpolecenia będzie prawdopodobnie najszybszą opcją.

Ale prawdopodobnie będziesz chciał naprawić ustawienia regionalne na C.

sort -unie zgłasza unikalnych wierszy, ale jeden z każdego zestawu wierszy sortujących to samo. W ustawieniach regionalnych C 2 różne linie niekoniecznie muszą być takie same, ale nie jest tak w przypadku większości ustawień narodowych opartych na UTF-8 w systemach GNU.

Ponadto użycie ustawień regionalnych C pozwala uniknąć nakładów związanych z analizowaniem UTF-8 i przetwarzaniem złożonych zamówień sortowania, co znacznie poprawiłoby wydajność.

Więc:

LC_ALL=C sort -u file

Możesz także poprawić wydajność, używając szybszego dysku (lub innego niż ten, na którym znajdują się pliki wejściowe i / lub wyjściowe) dla plików tymczasowych (przy użyciu -Tlub $TMPDIRzmiennej środowiskowej), lub bawiąc się -Sopcją obsługiwaną przez niektóre sortimplementacje) .

W przypadku niektórych typów danych wejściowych lub do wolnego przechowywania, użycie --compress-programopcji GNU sort(na przykład z lzop) może poprawić wydajność oprócz wykorzystania pamięci.


Teraz tylko uwaga dla tych, którzy sprzeciwiają się (słusznie do pewnego stopnia), że nie będzie to właściwa kolejność :

Zgadzam się, że jako człowiek chciałbym zobaczyć Stéphane'a między Stefanem a Stephanie , ale:

  • Komputer chciałby Stéphane aby porządek ponieważ é(przynajmniej jeśli wyrażone jako U + 00E9) jako znaku lub bajtów jego kodowanie UTF-8 rodzajów po (w zakresie punktów kodowych lub wartości bajtów). To porządek sortowania, który jest bardzo prosty do wdrożenia i jest ścisłym porządkiem całkowitym i nie dziwi.
  • Porządek sortowania twojego regionu prawdopodobnie nie będzie satysfakcjonujący w wielu przypadkach, nawet dla człowieka. Na przykład w moim systemie z domyślnymi ustawieniami narodowymi en_GB.utf8:

    • Stéphane i Stéphane (jeden z U + 00E9, drugi z eU + 0301) nie sortują tego samego:

      $ printf '%b\n' 'Ste\u0301phane' 'St\u00e9phane' | sort -u
      Stéphane
      Stéphane
      
    • ale ③, ①, ② wszystkie są takie same (oczywiście błąd w tych definicjach ustawień regionalnych):

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

      Tutaj jest ③, ale równie dobrze może być ① lub ②

Więc IMO, są szanse, że zawsze będziesz chciał sort -uz LC_ALL = C, jeśli chcesz unikalnych linii. A jeśli chcesz, aby wynikowa lista była sortowana w kolejności sortowania użytkownika, przesuń ją do sort:

LC_ALL=C sort -u | sort

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

8
+1 za ustawienie regionalne: może to mieć ogromny wpływ na wydajność
Adrian Pronk

1
Tak. plik sortujący zawierający 250000 linii LC_ALL przyspiesza rzeczy 8 razy.
Jan Vlcinsky,

-1

Oto gotowy do użycia skrypt bash do sortowania danych w skali TB na zwykłym komputerze z kilkoma GB RAM: http://sgolconda.blogspot.com/2015/11/sort-very-large-dataset.html Sprawdza liczbę rdzenie maszyny jako i używa wszystkich rdzeni. Może sortować pliki numeryczne lub ciągowe. Może służyć do znajdowania unikalnych rekordów w danych w skali TB.


To nie jest dobra sugestia. Skrypt jest bardzo rozdęty i dzieli plik wejściowy, aby posortować części, które według akceptowanej odpowiedzi nie są potrzebne przy sortowaniu GNU.
Thorbjørn Ravn Andersen
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.