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?

evachrystyna
źródło
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ę.

Graeme
źródło
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
Stéphane Chazelas
źródło
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.

użytkownik213743
źródło
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