Come ordinare i file di grandi dimensioni?


35

Ho un PC con CPU Intel (R) Pentium (R) G640 a 2,80 GHz e 8 GB di RAM. Sto usando Scientific Linux 6.5 su di esso con il filesystem EXT3.

Con questa configurazione, qual è il modo più veloce che posso fare sort -usu un file da 200 gigabyte?

Devo dividere il file in file più piccoli (inferiori a 8 GB) sort -u, metterli insieme, quindi dividerli di nuovo in una dimensione diversa, di sort -unuovo, ecc.? O ci sono script di ordinamento, programmi che potrebbero gestire file così grandi con la mia quantità limitata di RAM?


6
Si prega di modificare la tua domanda e spiegare che cosa accade quando si tenta il comando che avete inviato. A corto di spazio su disco? Il comando dovrebbe funzionare fintanto che hai abbastanza spazio libero sul tuo /tmp.
terdon


1
La risposta prescelta dice sostanzialmente quello che dice @terdon, ma dai un'occhiata anche a questo - stackoverflow.com/a/13025731/2801913 . Per questo, avrai bisogno di GNU, parallelpiuttosto che dei moreutils parallelinstallati di default su alcuni sistemi.
Graeme,

1
È possibile caricare il file su Amazon S3, quindi eseguire un processo Elastic Map Reduce con alcune centinaia di nodi per ordinarlo!
Alan Shutko,

2
sort(1)potrebbe rimanere senza spazio /tmp; in tal caso, puoi designare un'altra area per i file temporanei con la variabile di ambiente TMPDIRo flag-T=<tmpdir>
vonbrand

Risposte:


46

GNU sort(che è l'impostazione predefinita sulla maggior parte dei sistemi Linux), ha --parallelun'opzione. Da http://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html :

'--Parallel = n'

Imposta il numero di ordinamenti eseguiti in parallelo su n. Per impostazione predefinita, n è impostato sul numero di processori disponibili, ma limitato a 8, poiché dopo ciò si riducono le prestazioni. Si noti inoltre che l'utilizzo di n thread aumenta l'utilizzo della memoria di un fattore del registro n. Vedi anche invocazione nproc.

Poiché la tua cpu ha 2 core, puoi fare:

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

È meglio specificare il numero effettivo di core poiché potrebbe apparire maggiore a causa del hyper-threading del processore .

È inoltre possibile sperimentare niceper influenzare la priorità di pianificazione del processore e influenzare la pianificazione ioniceI / O. Puoi aumentare la priorità rispetto ad altri processi come questo, non credo che questo ti darà grandi risparmi in quanto sono generalmente migliori per assicurarsi che un processo in background non usi troppe risorse. Tuttavia puoi combinarli con qualcosa del tipo:

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

Si noti inoltre che, come ha commentato Gilles , l'utilizzo di un singolo comando di ordinamento GNU sarà più veloce di qualsiasi altro metodo di suddivisione dell'ordinamento poiché l'algoritmo è già ottimizzato per gestire file di grandi dimensioni. Qualsiasi altra cosa probabilmente rallenterà le cose.


10
E dovresti notare che chiamare sortdirettamente è meglio di qualsiasi altra cosa tu possa ingannare. L'ordinamento GNU è progettato per far fronte bene a file molto più grandi della RAM.
Gilles 'SO- smetti di essere malvagio' il

L'opzione --parallel sort non funziona sui miei server RH6.5. Sort --version pensa che provenga da coreutils 8.4. Di quale versione ho bisogno per la versione parallela?
markus_b

3
Vedi anche superuser.com/questions/938558/sort-parallel-isnt-parallelizing : potresti dover specificare qualcosa come -S512M se noti che in realtà non sta parallelizzando.
Unhammer,

46

L'uso del sortcomando sarà probabilmente l'opzione più veloce.

Ma probabilmente vorrai correggere le impostazioni locali su C.

sort -unon riporta righe univoche, ma una di ciascuna serie di righe che ordinano la stessa. Nella locale C, 2 linee diverse non necessariamente ordinano la stessa cosa, ma non è il caso nella maggior parte delle versioni locali basate su UTF-8 sui sistemi GNU.

Inoltre, l'uso della locale C evita il sovraccarico di dover analizzare UTF-8 e di elaborare ordinamenti complessi, migliorando notevolmente le prestazioni.

Così:

LC_ALL=C sort -u file

È inoltre possibile migliorare le prestazioni utilizzando un'unità più veloce (o un'unità diversa da quella in cui si trovano i file di input e / o output) per i file temporanei (utilizzo -To $TMPDIRvariabile d'ambiente), oppure giocherellare con l' -Sopzione supportata da alcune sortimplementazioni) .

Per alcuni tipi di input o per l'archiviazione lenta, l'utilizzo --compress-programdell'opzione GNU sort(ad esempio con lzop) potrebbe migliorare le prestazioni oltre all'utilizzo dell'archiviazione.


Ora solo una nota per coloro che obiettano (giustamente in una certa misura) che non sarà l'ordine corretto :

Sono d'accordo sul fatto che come umano, vorrei vedere Stéphane ordinare tra Stefan e Stephanie , ma:

  • Un computer vorrebbe che Stéphaneé ordinasse da allora in poi (almeno quando espresso come U + 00E9) come carattere o byte dopo la sua codifica UTF-8 (in termini di punto di codice o valore in byte). Questo è un ordinamento che è molto semplice da implementare ed è un ordine totale rigoroso e non sorprende.
  • L'ordinamento del tuo locale probabilmente non sarà soddisfacente in molti casi neanche per un essere umano. Ad esempio sul mio sistema con le impostazioni internazionali en_GB.utf8:

    • Stéphane e Stéphane (uno con U + 00E9, l'altro con eU + 0301) non ordinano lo stesso:

      $ printf '%b\n' 'Ste\u0301phane' 'St\u00e9phane' | sort -u
      Stéphane
      Stéphane
      
    • ma ③, ①, ② ordinano tutti lo stesso (ovviamente un bug in quelle definizioni locali):

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

      Qui è ③, ma avrebbe potuto anche essere ① o ②

Quindi, IMO, è probabile che tu voglia sempre sort -ucon LC_ALL = C, se vuoi linee uniche. E se si desidera che l'elenco risultante venga ordinato nell'ordinamento dell'utente, reindirizzarlo sortnuovamente:

LC_ALL=C sort -u | sort

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

8
+1 per l'impostazione delle impostazioni internazionali: può avere un effetto enorme sulle prestazioni
Adrian Pronk,

1
Sì. ordinando file con 250000 linee, LC_ALL accelera le cose 8 volte.
Jan Vlcinsky,

-1

Ecco uno script bash pronto per l'uso per ordinare i dati della scala TB su una macchina normale con un paio di ram GB: http://sgolconda.blogspot.com/2015/11/sort-very-large-dataset.html Verifica il numero di core la tua macchina come e usa tutti i core. Può ordinare file numerici o di stringhe. Può essere utilizzato per trovare record univoci nei dati della scala TB.


Questo non è un buon suggerimento. Lo script è immensamente gonfio e divide il file di input per ordinare le parti che la risposta accettata sottolinea non è necessaria con l'ordinamento GNU.
Thorbjørn Ravn Andersen,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.