Сортуйте алгоритми, які працюють на великій кількості даних


12

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

Єдиним кандидатом, який я до цього часу знайшов, є сортування злиття: ви можете реалізувати алгоритм таким чином, щоб він сканував ваш набір даних при кожному злитті, не утримуючи відразу всі дані в основній пам'яті. Про маю на увазі зміну сорту злиття описано в цій статті в розділі Використання стрічкових накопичувачів .

Я думаю, що це хороше рішення (зі складністю O (nx log (n)), але мені цікаво дізнатись, чи існують інші (можливо швидші) алгоритми сортування, які можуть працювати на великих наборах даних, які не входять в основну пам'ять.

EDIT

Ось ще кілька деталей, як цього вимагають відповіді:

  • Дані потрібно періодично сортувати, наприклад, раз на місяць. Мені не потрібно вставляти кілька записів і поступово сортувати дані.
  • У моєму прикладі текстовий файл становить близько 1 Гб тексту UTF-8, але я хотів вирішити проблему в цілому, навіть якщо цей файл був, скажімо, 20 ГБ.
  • Він не знаходиться в базі даних, і через інші обмеження цього не може бути.
  • Ці дані скидаються іншими як текстовий файл, у мене є власний код для читання цього текстового файлу.
  • Формат даних - це текстовий файл: нові символи рядків є роздільниками записів.

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


1
Які дані? Різні набори даних можуть означати різні алгоритми, які найкраще відповідають вашим цілям.
whatsisname

Це текстовий файл, і я повинен сортувати рядки. Рядки не мають фіксованої довжини, але довжина не дуже варіюється (близько 50 символів на запис).
Джорджіо

3
Я не знаю вашого середовища чи ваших обмежень, але я б використовував базу даних для сортування, коли це можливо. Це тому, що це майже 100% стійкість до помилок і буде набагато ефективнішим, ніж мій код.
NoChance

Я працюю на Linux / Java. Я здійснив сортування злиття, і, здається, він працює досить гладко. Сортування декількох мільйонів рядків займає досить багато часу, але мені потрібно це робити раз у раз.
Джорджіо

@Giorgio, добре, що ти реалізував такий алгоритм. Для виробничих робіт я все ж пропоную використовувати базу даних. Не тільки за швидкістю, але і за надійністю та простотою обслуговування.
NoChance

Відповіді:


13

Канонічне посилання на сортування та пошук - Knuth, Vol. 3 . Почніть з цього.

Книга спочатку була написана ще тоді, коли комп'ютери були набагато меншими та повільнішими, ніж зараз, що зробило методи сортування поза пам’яттю важливішими, ніж вони сприймаються сьогодні.


2
Дякую за довідку: я майже впевнений, що знайду цікавий матеріал у книзі Кнут. Я не впевнений, що методи сортування поза пам'яттю сьогодні не актуальні. Можливо, не для загальних щоденних завдань, але я можу собі уявити, що все ще існує маса ситуацій, в яких потрібно обробити дуже великі набори даних.
Джорджіо

Алгоритми Кнута завжди корисні. Наприклад, об'єднання сортування з буфером купівлі-сортування може бути дуже ефективним і ДУЖЕ легко здійснити.
Султан

4
Не дуже корисна відповідь, оскільки згаданий матеріал не є безкоштовним. Що стосується ОП, я пропоную гугл для відповіді. Вам не потрібно обкладати 50 доларів, щоб отримати книгу, коли подібну інформацію ви можете знайти, копаючи в Інтернеті. Звичайно, ви, ймовірно, можете безкоштовно завантажити це також з ( ах ) певних сайтів. Навряд чи заслуговує на прийняту відповідь.
Томас Едінг

1
@ThomasEding, є такі речі, які називаються "бібліотеками", які містять велику кількість цих застарілих пристроїв зберігання та пошуку інформації, що називаються "книгами". "Бібліотеки" роблять "книги" доступними для БЕЗКОШТОВНОЇ позики. Якщо у вашій конкретній "бібліотеці" немає конкретної "книги", яку ви шукаєте, вони також пропонують БЕЗКОШТОВНУ послугу під назвою "міжбібліотечна позика", яка дозволяє "бібліотеці" позичити "книгу" у іншої "бібліотеки", щоб вони могли позику вам.
Джон Р. Стром

6

Зовнішнє злиття R-Way, як і в sortкоманді UNIX, є хорошою альтернативою. З вашої рецептури я не впевнений, чи це алгоритм, який ви мали на увазі під "сортуванням злиття", і якщо ви цього не знаєте, подивіться.


Дякую. Зовнішнє злиття R-Way, здається, відрізняється від того, що я мав на увазі. Цікаве читання.
Джорджіо

4

Без більшої конкретності "Об'єднати сортування" - це, мабуть, найкраща відповідь, яку ви отримаєте, проте ви можете реалізувати щось набагато розумніше залежно від ваших вимог.

Наприклад, ви можете просто створити індекс пам'яті файлу, а потім скопіювати всі значення одразу, кешуючи розташування різних ключових значень? Чи 1/2 вписується в пам'ять відразу, або 1/1000000? Якщо це друга, то, можливо, ви не зможете помістити індекс в пам'ять, якщо перша, то ви зможете ефективніше сортувати обидві половинки, а потім з’єднати їх разом за один останній крок.

Чорт, оскільки ви не вказали, можливо, ваші дані знаходяться в базі даних, якщо так, ви можете просто створити таблицю індексів і назвати це добре (я здогадуюсь, що це не так, але просто вказавши на це Ваша ситуація має вирішальне значення для вирішення такої складної проблеми, як ця).

Якщо ви хочете зробити це один раз і шукаєте дуже швидкий злом, це здається, що зовнішній сорт злиття був би гарним початком, якщо ви працюєте з Unix (оскільки він, мабуть, вбудований)

Якщо вам доведеться утримувати його в порядку та завжди додавати одну запис, тоді буде необхідним сортування вставки (Додавання одного запису до відсортованих даних - це завжди спосіб вставки).

Чи можете ви керувати кодом, який "читає" дані? Якщо так, то багато форм індексації (а не сортування за допомогою переміщення даних на диску) допоможуть ЛОТУ (насправді це буде абсолютна вимога).

Так:

  • На місці чи кілька файлів?
  • Одноразово, періодично чи постійно його сортувати?
  • На скільки більше пам’яті (скільки навантажень пам’яті, щоб пройти через весь набір даних)?
  • Це в базі даних? Чи може бути?
  • Чи контролюєте ви код, який читає дані, чи інші завантажують файл безпосередньо?
  • Формат файлу? (Текст? Виправлений запис?)
  • Будь-які інші особливі обставини, про які я не питав?

Дякую за відповідь. Що ви маєте на увазі під словом "На місці чи декількома записами"?
Джорджіо

Вибачте, я мав би прочитати мою відповідь - я мав на увазі кілька файлів. На місці в значній мірі мається на увазі фіксований розмір запису та індексація, в який момент ви, мабуть, хочете базу даних.
Білл К

Ні, це не на місці: записи не мають фіксованого розміру. Я використовую чотири тимчасові файли для моєї поточної реалізації.
Джорджіо

Чи можете ви інтерпретувати вихід з кодом чи він повинен бути у певному форматі (плоский текстовий файл?) Як часто його потрібно сортувати - кожен раз, коли щось додається або просто періодично? Коли щось додається, це просто додається до кінця чи ви можете написати код, який додає його?
Білл К

Кожен рядок може бути проаналізований на запис (файл - це файл CSV), але більшість полів є текстовими. Сортувати її потрібно раз у раз (наприклад, щомісяця), і це займає близько 1 години для сортування за моєю поточною реалізацією. Для вставки рядка я міг би написати код, який вставляє рядок у потрібному місці: з кодом, який я маю до цього часу, знадобиться 20 хвилин, щоб написати такий інструмент.
Джорджіо

3

Якщо ви дійсно хочете масштабованого рішення, вам слід поглянути на TeraSort, стандартну реалізацію сортування із зменшенням карт; докладніше про StackOverflow .


1
+1: Цікаве посилання. Чи не злиття є сортуванням прикладу відображення / зменшення, де карта відповідає сортуванням підсписів, а зменшення відповідає злиттям?
Джорджіо

Це може бути видно, але ви можете використовувати Hadoop для цього, а не писати його самостійно.
m3th0dman

1

Можливо, вас зацікавить сорт відра . Середня ефективність випадку - лінійний час.

= O (n + d) n: кількість елементів і d = довжина найбільшої кількості, якщо ви маєте інтуїцію щодо своїх даних, тобто. Якщо ви знаєте, скільки довгих цифр - це ваше найбільше число. Отже, якщо у вас є 2 мільйони 6-значних чисел => 0 (n), таким чином, лінійними.


0

Використовуйте зовнішній алгоритм сортування злиття (якщо ваші дані Утримання), або блокова сортування з підрахунком начебто як реалізація сортування для відра (якщо ваші дані є дискретними і рівномірно розподілені).

Можливо, найкращим підходом є створення власного файлу індексу / відображення, якщо приріст невеликий.

  1. Як-небудь замовити свою "базу даних"
  2. Призначте ціле число кожному запису (1, 2, 3, 4, ..., n) (краще: використовуйте кілька розріджених індексів)
  3. Додаючи приріст, просто знайдіть пробіл, де ліве число менше або рівне, а праве число більше або рівне (це не повинно бути складно з деякою модифікованою версією двійкового пошуку)
  4. Вставте, тоді як прогалини досить великі, якщо ні: просто перевстановіть (ніколи не сортуйте знову) :-)

0

Я щойно створив абстрактні структури, які називаються великою чергою та великим масивом, щоб спростити завдання сортування великих даних та пошук на одній машині з обмеженою пам’яттю. В основному, алгоритм, що використовується, схожий на той, який ви згадали вище - сортування зовнішнього злиття.

Я можу сортувати дані 128 ГБ (кожен елемент по 100 байтів) за 9 годин на одній машині, а потім двійковим пошуком відсортованих даних майже немає часу.

Ось пост про те, як шукати великі дані за допомогою моєї великої черги з відкритим кодом та великих масивів.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.