Як сортувати великі файли?


35

У мене є ПК з процесором Intel (R) Pentium (R) G640 при 2,80 ГГц і 8 ГБ оперативної пам’яті. Я працюю на ньому Linux Linux 6.5 з файловою системою EXT3.

Налаштування, який найшвидший спосіб зробити у sort -uфайлі на 200 гігабайт?

Чи слід розділити файл на менші файли (розміром менше 8 ГБ), sort -uскласти їх, а потім знову розділити їх іншим розміром, sort -uзнову тощо? Або є якісь скрипти сортування, програми, які могли б обробляти файли такого великого розміру з моєю обмеженою кількістю оперативної пам’яті?


6
Будь ласка , змініть своє питання і пояснити , що відбувається , коли ви намагаєтеся команда , яку відправила. У вас не вистачає місця на диску? Команда повинна працювати до тих пір, поки у вас буде достатньо вільного місця на вашому /tmp.
terdon


1
Обрана відповідь в основному говорить, що говорить @terdon, але також перевірити це - stackoverflow.com/a/13025731/2801913 . Для цього вам знадобиться GNU, parallelа не більш корисні програми, parallelякі встановлені за замовчуванням у деяких системах.
Graeme

1
Ви можете завантажити файл на Amazon S3, а потім розкрутити завдання зменшення еластичної карти на кілька сотень вузлів, щоб сортувати його!
Алан Шутко

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 :

'--паралельно = n'

Встановіть кількість різновидів, які проходять паралельно n. За замовчуванням n встановлюється на кількість доступних процесорів, але обмежується 8, оскільки після цього є зменшення підвищення продуктивності. Зауважте також, що використання n потоків збільшує використання пам'яті на коефіцієнт журналу 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 призначене для того, щоб добре впоратися з файлами, які значно більше, ніж оперативна пам'ять.
Жил 'ТАК - перестань бути злим'

Параметр сортування --parallel не працює на моїх серверах RH6.5. Сортувати - перехід вважає, що воно виходить із основних елементів 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 за замовчуванням:

    • Stéphane та Stéphane (один з U + 00E9, другий з eU + 0301) не сортують те саме:

      $ printf '%b\n' 'Ste\u0301phane' 'St\u00e9phane' | sort -u
      Stéphane
      Stéphane
      
    • але ③, ①, sort всі подібні (очевидно, помилка в цих визначеннях локалі):

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

      Ось це ③, але це так само могло бути ① чи ②

Тож 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 для налаштування місцевості: це може мати величезний вплив на продуктивність
Адріан Пронк,

1
Так. сортування файлу з 250000 рядків LC_ALL прискорює роботу в 8 разів.
Ян Вльчинський

-1

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


Це не гарна пропозиція. Сценарій надзвичайно роздутий і розбиває вхідний файл для сортування частин, на які вказується прийнята відповідь, не потрібен при сортуванні GNU.
Thorbjørn Ravn Andersen
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.