Как сортировать большие файлы?


35

У меня есть ПК с процессором Intel® Pentium® G640 с тактовой частотой 2,80 ГГц и 8 ГБ оперативной памяти. Я использую Scientific Linux 6.5 на нем с файловой системой EXT3.

На этой установке, какой самый быстрый способ я могу сделать sort -uна 200-гигабайтном файле?

Должен ли я разделить файл на более мелкие файлы (размером менее 8 ГБ), sort -uобъединить их, затем снова разделить на другой размер, sort -uснова и т. Д.? Или есть какие-нибудь сценарии сортировки, программы, которые могут обрабатывать файлы с таким большим объемом памяти?


6
Пожалуйста, отредактируйте свой вопрос и объясните, что происходит, когда вы пытаетесь опубликовать команду Вам не хватает места на диске? Команда должна работать до тех пор, пока у вас достаточно свободного места /tmp.
Terdon


1
Выбранный ответ в основном говорит о том, что говорит @terdon, но также проверьте этот - stackoverflow.com/a/13025731/2801913 . parallelЯ думаю, что для этого вам понадобится GNU, а не moreutils parallel, установленный по умолчанию в некоторых системах.
Грэм

1
Вы можете загрузить файл в Amazon S3, а затем раскрутить задание Elastic Map Reduce с несколькими сотнями узлов, чтобы отсортировать его!
Алан Шутко

2
sort(1)может не хватить места на /tmp; если это так, вы можете назначить другую область для временных файлов с помощью переменной среды TMPDIRили флага-T=<tmpdir>
vonbrand

Ответы:


46

GNU sort(который используется по умолчанию в большинстве систем Linux), имеет --parallelопцию. С http://www.gnu.org/software/coreutils/manual/html_node/sort-invocation.html :

'--Parallel = п'

Установите количество сортировок, запущенных параллельно, на n. По умолчанию для n установлено число доступных процессоров, но оно не должно превышать 8, поскольку после этого наблюдается снижение производительности. Также обратите внимание, что использование n потоков увеличивает использование памяти в log n. Также смотрите вызов nproc.

Поскольку ваш процессор имеет 2 ядра, вы можете сделать:

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

Лучше указать фактическое количество ядер, так как может показаться, что их больше из-за того, что процессор имеет гиперпоточность .

Вы также можете поэкспериментировать с niceвлиянием приоритета планирования процессора и планированием ioniceввода / вывода. Вы можете увеличить приоритет над другими процессами, подобными этим, я не думаю, что это даст вам большую экономию, поскольку они обычно лучше для обеспечения того, чтобы фоновый процесс не использовал слишком много ресурсов. Тем не менее, вы можете объединить их с чем-то вроде:

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

Также обратите внимание, что, как прокомментировал Жиль , использование одной команды сортировки GNU будет быстрее, чем любой другой метод разрушения сортировки, поскольку алгоритм уже оптимизирован для обработки больших файлов. Все остальное, скорее всего, только замедлит ход событий.


10
И вы должны заметить, что звонить sortнапрямую лучше, чем что-либо еще, что вы могли бы сделать. Сортировка GNU разработана для того, чтобы хорошо справляться с файлами, которые намного больше, чем RAM.
Жиль "ТАК - перестань быть злым"

Опция сортировки --parallel не работает на моих серверах RH6.5. Sort --version считает, что это происходит из coreutils 8.4. Какая версия мне нужна для параллельной версии?
markus_b

3
См. Также superuser.com/questions/938558/sort-parallel-isnt-parallelizing - вам может потребоваться указать что-то вроде -S512M, если вы заметите, что на самом деле это не распараллеливание.
unhammer

46

Использование sortкоманды, вероятно, будет самым быстрым вариантом.

Но вы, вероятно, захотите исправить локаль до C.

sort -uне сообщает об уникальных строках, но об одном наборе строк, которые сортируются одинаково. В языковом стандарте C две разные строки обязательно не сортируются одинаково, но это не так в большинстве языковых стандартов на основе UTF-8 в системах GNU.

Кроме того, использование языкового стандарта C позволяет избежать дополнительных затрат на анализ UTF-8 и обработку сложных порядков сортировки, что значительно повышает производительность.

Так:

LC_ALL=C sort -u file

Вы также можете повысить производительность, используя более быстрый диск (или диск, отличающийся от того, на котором находятся входные и / или выходные файлы) для временных файлов (используя переменную среды -Tили $TMPDIRпеременную среды), или переключившись на -Sпараметр, поддерживаемый некоторыми sortреализациями) ,

Для некоторого типа ввода или для медленного хранения использование --compress-programопции GNU sort(например, с lzop) может улучшить производительность в дополнение к использованию хранилища.


Теперь просто отметим для тех, кто возражает (справедливо в некоторой степени), что это будет неправильный порядок :

Я согласен, что как человек, я хотел бы видеть Стефана между Стефаном и Стефани , но:

  • Компьютер хотел бы Stephane к своего рода после того, как так é(по крайней мере , когда выражается в виде U + 00E9) в качестве символа или байтов его UTF-8 кодировкой сортов после (с точки зрения стоимости или элемент кода байта). Это порядок сортировки, который очень прост в реализации, является строгим общим порядком и не вызывает удивления.
  • Порядок сортировки вашей локали, вероятно, не будет удовлетворительным во многих случаях даже для человека. Например, в моей системе со стандартным языком en_GB.utf8:

    • Стефан и Стефан (один с U + 00E9, другой с eU + 0301) не сортируют одно и то же:

      $ printf '%b\n' 'Ste\u0301phane' 'St\u00e9phane' | sort -u
      Stéphane
      Stéphane
      
    • но ③, ①, ② все сортируются одинаково (очевидно, ошибка в этих определениях локали):

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

      Вот, это but, но с таким же успехом это могло быть ① или ②

Итак, IMO, скорее всего, вы всегда хотите sort -uс LC_ALL = C, если вы хотите уникальные строки. И если вы хотите, чтобы этот результирующий список был отсортирован в порядке сортировки пользователя, передайте его sortснова:

LC_ALL=C sort -u | sort

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

8
+1 за настройку локали: это может оказать огромное влияние на производительность
Adrian Pronk

1
Да. Сортировка файла с 250000 строками LC_ALL ускоряет работу в 8 раз.
Ян Влчинский

-1

Вот готовый скрипт bash для сортировки данных в масштабе ТБ на обычном компьютере с парой оперативной памяти в ГБ: http://sgolconda.blogspot.com/2015/11/sort-very-large-dataset.html Проверяет количество Ядро вашей машины как и использует все ядра. Можно сортировать, числовые или строковые файлы. Может использоваться для поиска уникальных записей в данных шкалы ТБ.


Это не очень хорошее предложение. Скрипт очень раздут и разбивает входной файл для сортировки частей, которые, как указывает принятый ответ, не нужны для сортировки GNU.
Турбьерн Равн Андерсен
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.