Como ordenar arquivos grandes?

29

Eu tenho um PC com Intel Pentium (R) CPU G640 a 2,80 GHz e 8 GB de RAM. Estou executando o Scientific Linux 6.5 nele com o sistema de arquivos EXT3.

Nesta configuração, qual é a maneira mais rápida de fazer um sort -u em um arquivo de 200 gigabytes?

Devo dividir o arquivo em arquivos menores (menores que 8 GB), sort -u , juntá-los, dividi-los novamente em um tamanho diferente, sort -u novamente etc.? Ou existem scripts de classificação, programas que poderiam lidar com arquivos tão grandes com minha quantidade limitada de RAM?

    
por evachristine 17.03.2014 / 19:49

3 respostas

39

GNU sort (que é o padrão na maioria dos sistemas Linux), possui uma opção --parallel . De link :

‘--parallel=n’

Set the number of sorts run in parallel to n. By default, n is set to the number of available processors, but limited to 8, as there are diminishing performance gains after that. Note also that using n threads increases the memory usage by a factor of log n. Also see nproc invocation.

Como sua CPU tem 2 núcleos, você poderia fazer:

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

É melhor especificar o número real de núcleos, pois parece haver mais a ser devido ao processador ter hyper-threading .

Você também pode experimentar com nice para influenciar a prioridade de agendamento do processador e ionice para influenciar o agendamento de I / O. Você pode aumentar a prioridade sobre outros processos como este, eu não acho que isso vai te dar uma grande economia, pois eles geralmente são melhores para garantir que um processo em segundo plano não use recursos demais . Nunca, a menos, você pode combiná-los com algo como:

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

Note também que, como Gilles comentou, usando um O único comando GNU sort será mais rápido do que qualquer outro método de decompor a classificação, pois o algoritmo já está otimizado para lidar com arquivos grandes. Qualquer outra coisa provavelmente vai atrasar as coisas.

    
por 17.03.2014 / 20:53
39

Usar o comando sort provavelmente será a opção mais rápida.

Mas provavelmente você desejará corrigir a localidade para C.

sort -u não informa linhas exclusivas, mas um de cada conjunto de linhas que ordenam o mesmo. Na localidade C, 2 linhas diferentes não necessariamente ordenam o mesmo, mas esse não é o caso na maioria das localidades baseadas em UTF-8 nos sistemas GNU.

Além disso, usar a localidade C evita a sobrecarga de ter que analisar o UTF-8 e processar ordens de classificação complexas para melhorar drasticamente o desempenho.

Então:

LC_ALL=C sort -u file

Você também pode melhorar o desempenho usando uma unidade mais rápida (ou uma unidade diferente daquela onde os arquivos de entrada e / ou saída são) para os arquivos temporários (usando -T ou $TMPDIR variável de ambiente) ou mexendo na opção -S suportada por algumas sort implementações).

Para algum tipo de entrada ou para armazenamento lento, usar a opção --compress-program do GNU sort (por exemplo, com lzop ) pode melhorar o desempenho além do uso do armazenamento.

Now just a note for those objecting (rightly to some extent) that it will not be the correct order:

I agree that as a human, I'd like to see Stéphane sort in between Stefan and Stephanie, but:

  • A computer would want Stéphane to sort after since é (at least when expressed as U+00E9) as a character or the bytes of its UTF-8 encoding sorts after (in terms of codepoint or byte value). That's a sort order that is very simple to implement and is a strict total order and has no surprise.
  • Your locale's sort order will likely not be satisfactory in many cases either even to a human. For example on my system with the default en_GB.utf8 locale:

    • Stéphane and Stéphane (one with U+00E9, the other with eU+0301) don't sort the same:

      $ printf '%b\n' 'Ste\u0301phane' 'St\u00e9phane' | sort -u
      Stéphane
      Stéphane
      
    • but ③, ①, ② all sort the same (obviously a bug in those locale definitions):

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

      Here, it's ③, but it could just as well have been ① or ②

So IMO, chances are you always want sort -u with LC_ALL=C, if you want unique lines. And if you want that resulting list to be sorted in the user's sort order, pipe it to sort again:

LC_ALL=C sort -u | sort

LC_ALL=C sort | LC_ALL=C uniq -c | sort -k2
    
por 17.03.2014 / 21:27
-2

Aqui está um script pronto para usar a classificação dos dados da escala TB em uma máquina comum com um par de ram GB: link Ele verifica o número de núcleos de sua máquina e usa todos os núcleos. Pode classificar arquivos numéricos ou de string. Pode ser usado para encontrar registros únicos em dados de escala de TB.

    
por 02.02.2017 / 01:04

Tags