Сортування вмісту надзвичайно великого (800 ГБ) текстового файлу у Windows


20

Я маю текст файл з словом у кожному рядку, розмір файлу - 800 Гб. Мені потрібно сортувати слова в алфавітному порядку.

Я спробував використати Windows сортувати використання програми:

sort.exe input.txt /o output.txt

що дає помилку: Недостатньо основної пам'яті для завершення сортування.

У мене 32 ГБ ОЗП тому, коли я намагаюся вказати 10 Гб пам'яті для сортування за допомогою:

sort.exe input.txt /o output.txt /M 10000000

Я отримав:

Попередження: вказаний обсяг пам'яті зменшується до доступної пам'яті.

Вхідний запис перевищує максимальну довжину. Вкажіть більший максимум.

Які мої варіанти?



10
Це не перехресний пост, я не машина, тому розміщення цього і видалення інших займає кілька хвилин!
MaYaN

3
У майбутньому дозволить спільноті перенести ваше запитання
Ramhound

4
У Linux можна застосувати це метод . З файлами 100 Мб, це не повинно бути великою проблемою.
Eric Duminil

3
Яку версію Windows ви використовуєте? Sort.exe з досить старим Windows Server 2012 R2 стверджує, що може виконувати зовнішню сортування з використанням тимчасового файлу на диску (без документування обмеження розміру). Спробуйте скористатися кнопкою / T, щоб вказати диск з вільним розміром 800 Гб для тимчасового файлу. І повідомлення про "вхідний запис перевищує максимальну довжину" здається не пов'язаним з простором - подивіться на параметр / REC і розгляньте, що таке термінатор лінії.
davidbak

Відповіді:


14

Які мої варіанти?

Спробуйте Freeware Командний рядок утиліти сортування CMSort .

Він використовує кілька тимчасових файлів, а потім об'єднує їх в кінці.

CMsort читає записи вхідного файлу, поки не буде досягнута налаштована пам'ять. Потім записи сортуються і записуються у тимчасовий файл. Це буде повторюватись, доки не будуть оброблені всі записи. Нарешті, всі тимчасові файли об'єднані у вихідний файл. Якщо доступної пам'яті достатньо, тимчасові файли не записуються і об'єднання не потрібне.

Один користувач повідомляє, що він сортував файл розміром 130 000 000 байт.

Якщо ви хочете самостійно налаштувати деякі коди, є також Сортування величезних текстових файлів - CodeProject - "Алгоритм сортування рядків у текстових файлах, розмір якого перевищує доступну пам'ять"


21
Вау, 130 мегабайт !!! +1
David Foerster

2
@DavidPostill Ви впевнені, що сортуєте з coreutils для вікон не є більш ефективним ( --parallel варіант, якщо у вас більше одного ядра ...)?
Hastur

22

Ще один варіант - завантажити файл у базу даних. E.G MySQL і MySQL Workbench.
Бази даних - ідеальні кандидати для роботи з великими файлами

Якщо вхідний файл містить лише слова, розділені новим рядком, це не повинно бути занадто жорстким.

Після встановлення бази даних і MySQL Workbench це потрібно зробити.
Спочатку створіть схему (це припускає, що слова не перевищуватимуть 255 символів, хоча ви можете змінити це, збільшивши значення аргументу). Перший стовпець "idwords" є первинним ключем.

CREATE SCHEMA `tmp` ;

CREATE TABLE `tmp`.`words` (
  `idwords` INT NOT NULL AUTO_INCREMENT,
  `mywords` VARCHAR(255) NULL,
  PRIMARY KEY (`idwords`));

По-друге, імпортуйте дані: Це дозволить імпортувати всі слова в таблицю (цей крок може зайняти деякий час. Моя порада полягає в тому, щоб спершу запустити тест з файлом невеликих слів і після того, як ви впевнені, що формат такий же, як і більший (скорочення таблицю .. IE Очистіть його і завантажте повний набір даних).

LOAD DATA LOCAL INFILE "C:\\words.txt" INTO TABLE tmp.words
LINES TERMINATED BY '\r\n'
(mywords);


Це посилання може допомогти отримати правильний формат для завантаження. https://dev.mysql.com/doc/refman/5.7/en/load-data.html
E.G Якщо вам потрібно пропустити перший рядок, виконайте наступне.

LOAD DATA LOCAL INFILE "H:\\words.txt" INTO TABLE tmp.words
-- FIELDS TERMINATED BY ','
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES
(mywords);

Нарешті, збережіть відсортований файл. Це може зайняти деякий час, в залежності від вашого ПК.

SELECT tmp.words.mywords
FROM tmp.words
order by tmp.words.mywords asc
INTO OUTFILE 'C:\\sorted_words.csv';

Ви також можете шукати дані за власним бажанням. E.G. Це дасть вам перші 50 слів у порядку зростання (починаючи з 0-го або першого слова).

SELECT tmp.words.mywords
FROM tmp.words
order by tmp.words.mywords asc
LIMIT 0, 50 ;

Удачі
Піт


2
Це IS правильна відповідь значним відривом.
MonkeyZeus

1
Цей підхід, безумовно, буде більш гнучким, особливо якщо ви виявите, що потрібно повторно запустити сортування в іншому порядку, наприклад.
barbecue

Мені все одно, як швидко ваш екземпляр MySQL , MariaDB або будь-який інший СУБД є, це не буде нікуди близько до продуктивності вставки SQLite працює на одній машині. Навіть з чимось таким же швидким, як SQLite ця кількість даних занадто багато (і повільно) для обробки (довіряйте мені, я спробував, що перший!), тому найкращим рішенням є сортування і видалення дублікатів спочатку потім вставити БД як от SQLite . Таким чином, хоча це рішення може бути дійсним у деяких випадках, це, звичайно, не для того, що я намагаюся зробити. Дякуємо, що ви знайшли час для публікації цього.
MaYaN

Замовлення по mywords візьметься назавжди. Навіть з LIMIT, це займе тільки стільки, скільки все це, тому що MySQL доведеться пройти через кожне значення mywords і замовляйте їх. Щоб виправити це, ви повинні зробити наступне після того, як ви це зробите LOAD DATA. Додати індекс до mywords. Тепер ви можете замовити цей стовпець, а не займати тисячоліття. І це є краще додати індекс після завантаження даних, а не під час створення таблиці (набагато швидше завантаження даних).
Buttle Butkus

3

sort

Існує безліч алгоритмів, які використовуються для сортування впорядкованих і не впорядкованих файлів [ 1 ] .
Оскільки всі ці алгоритми вже реалізовані, виберіть програму, яка вже перевірена.

В coreutils (з Linux, але доступний і для вікон [ 2 ] ), вона існує sort Команда, здатна працювати паралельно під багатоядерними процесорами: зазвичай її достатньо.

Якщо ваш файл настільки величезний ви можете допомогти обробці розбиття ( split -l ), файл у деяких фрагментах, можливо, використовуючи паралельний варіант ( --parallel ), і сортування наведених замовлені шматки з -m опція ( merge sort ).
Один з багатьох способів цього пояснюється тут (розділити файл, замовити окремі шматки, об'єднати замовлені шматки, видалити тимчасові файли).

Примітки:

  • У вікнах 10 існують так звані Підсистема Windows для Linux в якому весь приклад Linux буде здаватися більш природним.
  • Сортування з різними алгоритмами має різний час виконання, яке масштабується як функція кількості записів даних, які необхідно відсортувати (O (n m ), O (nlogn) ...).
  • Ефективність алгоритму залежить від порядку, який вже присутній у вихідному файлі.
    (Наприклад a сорт міхура є найбільш швидким алгоритмом для вже впорядкованого файлу - точно N -, але він не ефективний в інших випадках).

0

Щоб запропонувати альтернативне рішення Петру H, є програма q яка дозволяє командам стилю SQL проти текстових файлів. Команда нижче зробить те ж саме (запустити з командного рядка в тому ж каталозі, що і файл), не потрібно встановлювати SQL Workbench або створювати таблиці.

q "select * from words.txt order by c1"

c1 є скороченням для стовпця 1.

Можна виключити повторювані слова з

q "select distinct c1 from words.txt order by c1"

і надсилати вихід до іншого файлу

q "select distinct c1 from words.txt order by c1" > sorted.txt

Будь-яка ідея, чи буде це справлятися з файлом 800 gig?
Rawling

1
Я не впевнений на 100% - я тестував вище з файлом 1200 рядків (9KB). Сторінка розробників має сторінку "обмежень", яка не говорить про максимальний розмір файлу. Великий файл все одно може зіткнутися з проблемою пам'яті.
Brian

3
q не може обробити цю кількість даних, пам'ятаючи про це q використання SQLite за сценою, якщо я не міг завантажити дані безпосередньо на SQLite що змушує вас думати q може?
MaYaN
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.