Trier les algorithmes qui fonctionnent sur une grande quantité de données

12

Je recherche des algorithmes de tri qui peuvent fonctionner sur une grande quantité de données, c'est-à-dire qui peuvent fonctionner même lorsque l'ensemble de données ne peut pas être conservé dans la mémoire principale à la fois.

Le seul candidat que j'ai trouvé jusqu'à présent est le tri par fusion: vous pouvez implémenter l'algorithme de telle sorte qu'il analyse votre ensemble de données à chaque fusion sans conserver toutes les données dans la mémoire principale à la fois. La variation du type de fusion que j'ai en tête est décrite dans cet article dans la section Utilisation avec des lecteurs de bande .

Je pense que c'est une bonne solution (avec la complexité O (nx log (n)) mais je suis curieux de savoir s'il existe d'autres algorithmes de tri (éventuellement plus rapides) qui peuvent fonctionner sur de grands ensembles de données qui ne tiennent pas dans la mémoire principale.

ÉDITER

Voici quelques détails supplémentaires, comme requis par les réponses:

  • Les données doivent être triées périodiquement, par exemple une fois par mois. Je n'ai pas besoin d'insérer quelques enregistrements et de trier les données de manière incrémentielle.
  • Mon exemple de fichier texte est d'environ 1 Go de texte UTF-8, mais je voulais résoudre le problème en général, même si le fichier faisait, disons, 20 Go.
  • Il ne se trouve pas dans une base de données et, en raison d'autres contraintes, il ne peut pas l'être.
  • Les données sont transférées par d'autres sous forme de fichier texte, j'ai mon propre code pour lire ce fichier texte.
  • Le format des données est un fichier texte: les nouveaux caractères de ligne sont des séparateurs d'enregistrement.

Une amélioration possible que j'avais en tête était de diviser le fichier en fichiers suffisamment petits pour être triés en mémoire, et enfin de fusionner tous ces fichiers en utilisant l'algorithme que j'ai décrit ci-dessus.

Giorgio
la source
1
Quel genre de données? Différents ensembles de données peuvent signifier différents algorithmes qui conviennent le mieux à votre objectif.
whatsisname
C'est un fichier texte et je dois trier les lignes. Les lignes ne sont pas de longueur fixe mais la longueur ne varie pas trop (environ 50 caractères par enregistrement).
Giorgio
3
Je ne connais pas votre environnement ou vos contraintes, mais j'utiliserais une base de données pour trier autant que possible. En effet, il est presque à 100% à l'épreuve des erreurs et sera beaucoup plus efficace que mon code.
NoChance
Je travaille sur Linux / Java. J'ai implémenté le tri par fusion et cela semble fonctionner assez bien. Le tri de plusieurs millions de lignes prend un certain temps, mais je n'ai besoin de le faire que de temps en temps.
Giorgio
@Giorgio, il est bon que vous ayez implémenté un tel algorithme. Pour les travaux de production, je suggère toujours d'utiliser une base de données. Non seulement pour la vitesse mais aussi pour la fiabilité et la facilité d'entretien.
NoChance

Réponses:

13

La référence canonique sur le tri et la recherche est Knuth, Vol. 3 . Commencez par là.

Le livre a été écrit à l'origine lorsque les ordinateurs étaient beaucoup plus petits et plus lents qu'aujourd'hui, ce qui rendait les techniques de tri hors mémoire plus importantes qu'elles ne le semblent aujourd'hui.

John R. Strohm
la source
2
Merci pour la référence: je suis presque sûr que je trouverai des documents intéressants dans le livre de Knuth. Je ne suis pas sûr que les techniques de tri hors mémoire ne soient pas pertinentes aujourd'hui. Peut-être pas pour les tâches courantes et quotidiennes, mais je peux imaginer qu'il existe encore de nombreuses situations dans lesquelles de très grands ensembles de données doivent être traités.
Giorgio
Les algorithmes de Knuth sont toujours utiles. Par exemple, une fusion avec un tampon de tri en tas peut être très efficace et TRÈS facile à implémenter.
Sulthan
4
Pas une réponse très utile car le matériel référencé n'est pas gratuit. Pour l'OP, je suggère de googler pour une réponse. Vous n'avez pas besoin de débourser 50 dollars pour obtenir un livre lorsque vous trouvez ce type d'informations en fouillant sur le Web. Bien sûr, vous pouvez probablement télécharger ceci gratuitement à partir de ( ahem ) certains sites également. Mérite à peine une réponse acceptée.
Thomas Eding du
1
@ThomasEding, il y a ces choses appelées "bibliothèques", qui contiennent de grandes quantités de ces dispositifs de stockage et de récupération d'informations obsolètes appelés "livres". Les "bibliothèques" mettent des "livres" à disposition pour un prêt gratuit. Si votre "bibliothèque" particulière n'a pas le "livre" que vous recherchez, ils offrent également un service GRATUIT appelé "prêt entre bibliothèques", qui permet à la "bibliothèque" d'emprunter le "livre" d'une autre "bibliothèque", afin qu'ils puissent vous le prêter.
John R. Strohm
6

La fusion externe de R-Way comme dans la sortcommande UNIX est une bonne alternative. D'après votre formulation, je ne suis pas sûr que ce soit l'algorithme que vous vouliez dire avec "fusionner le tri", et si vous ne le connaissez pas, jetez un œil.

thiton
la source
Merci. La fusion externe de R-Way semble différente de ce que j'avais en tête. Lecture intéressante.
Giorgio
4

Sans plus de détails, "Merge Sort" est probablement la meilleure réponse que vous obtiendrez, mais vous pouvez implémenter quelque chose de beaucoup plus intelligent en fonction de vos besoins.

Par exemple, pouvez-vous simplement créer un index en mémoire du fichier, puis copier toutes les valeurs à la fois, en mettant en cache l'emplacement des différentes valeurs clés? Est-ce que 1/2 tient en mémoire à la fois, ou 1/1000000? Si c'est le second, vous ne pourrez peut-être pas ajuster un index en mémoire, si le premier, vous pouvez trier les deux moitiés plus efficacement, puis les fusionner ensemble en une seule dernière étape.

Enfer, puisque vous ne l'avez pas spécifié, il est possible que vos données soient toutes dans une base de données, si c'est le cas, vous pouvez simplement créer une table d'index et l'appeler bien (je suppose que ce n'est pas le cas, mais juste en soulignant que votre situation est critique pour résoudre un problème compliqué comme celui-ci).

Si vous voulez le faire une seule fois et que vous recherchez un hack très rapide, il semble que ce type de fusion externe serait un bon début si vous utilisez unix (car il est apparemment intégré)

Si vous devez le garder dans l'ordre et que vous ajoutez toujours un seul enregistrement, un tri par insertion sera nécessaire (l'ajout d'un seul enregistrement aux données triées est toujours un tri par insertion).

Pouvez-vous contrôler le code qui "lit" les données? Si c'est le cas, de nombreuses formes d'indexation (plutôt que de trier en déplaçant les données sur le disque) aideront A LOT (sera en fait une exigence absolue).

Donc:

  • Fichier en place ou multiple?
  • Une fois, périodique ou le garder trié en tout temps?
  • Combien plus grand que la mémoire (combien de charges de mémoire pour parcourir l'ensemble des données)?
  • Est-ce dans une base de données? Peut-il être?
  • Contrôlez-vous le code qui lit les données, ou est-ce que d'autres déverseront un fichier directement?
  • Format de fichier? (Texte? Enregistrement fixe?)
  • Y a-t-il d'autres circonstances spéciales dont je n'ai pas parlé?
Bill K
la source
Merci d'avoir répondu. Qu'entendez-vous par «en place ou enregistrement multiple»?
Giorgio
Désolé, j'aurais dû relire ma réponse - je voulais dire plusieurs fichiers. La mise en place implique à peu près des tailles d'enregistrement fixes et une indexation à quel point vous voudriez probablement une base de données.
Bill K
Non, il n'est pas en place: les enregistrements ne sont pas de taille fixe. J'utilise quatre fichiers temporaires pour mon implémentation actuelle.
Giorgio
Pouvez-vous interpréter la sortie avec du code ou doit-elle être dans un format spécifique (fichier texte plat?) À quelle fréquence doit-elle être triée - chaque fois que quelque chose est ajouté ou juste occasionnellement? Quand quelque chose est ajouté, est-il simplement ajouté à la fin ou pouvez-vous écrire le code qui l'ajoute?
Bill K
Chaque ligne peut être analysée dans un enregistrement (le fichier est un fichier CSV) mais la plupart des champs sont du texte. Il doit être trié de temps en temps (par exemple tous les mois) et il faut environ 1 heure pour trier avec mon implémentation actuelle. Pour insérer une ligne, je pourrais écrire le code qui insère la ligne au bon endroit: avec le code que j'ai jusqu'à présent, il me faudrait 20 minutes pour écrire un tel outil.
Giorgio
3

Si vous voulez vraiment une solution évolutive, vous devriez jeter un œil à TeraSort, l'implémentation de tri standard avec map-Reduce; plus de détails sur StackOverflow .

m3th0dman
la source
1
+1: Lien intéressant. Merge Sort n'est-il pas un exemple de carte / réduire, où la carte correspond au tri des sous-listes et la réduction correspond à la fusion?
Giorgio
Cela peut être vu ainsi, mais vous pouvez utiliser Hadoop pour le faire pour vous au lieu de l'écrire vous-même.
m3th0dman
1

Vous pourriez être intéressé par un tri par seau . La performance moyenne d'un cas est un temps linéaire.

= O (n + d) n: nombre d'éléments et d = longueur du plus grand nombre si vous avez une intuition à propos de vos données ie. Si vous savez combien de «chiffres» est votre plus grand nombre. Donc, si vous avez 2 millions de nombres à 6 chiffres => 0 (n) donc linéaire.

stonemetal
la source
0

Utilisez un algorithme de tri par fusion externe (si vos données sont des continuos) ou un tri par compartiment avec tri de comptage comme implémentation du tri pour les compartiments (si vos données sont discrètes et uniformément réparties).

La meilleure approche est probablement de créer votre propre fichier d'index / mapping si l'incrément est petit.

  1. Commandez en quelque sorte votre "base de données"
  2. Attribuez un entier à chaque entrée (1, 2, 3, 4, ..., n) (mieux: utilisez des index clairsemés)
  3. Lors de l'ajout d'un incrément, il suffit de trouver un écart où le nombre de gauche est inférieur ou égal et le bon nombre est supérieur ou égal (cela ne devrait pas être difficile avec une version modifiée d'une recherche binaire)
  4. Insérez, alors que les espaces sont suffisamment grands, sinon: réindexez (ne triez plus jamais) :-)
malejpavouk
la source
0

Je viens de construire des structures abstraites appelées grande file d'attente et grand tableau pour simplifier le tri des données volumineuses et la tâche de recherche sur une seule machine avec une mémoire limitée. Fondamentalement, l'algorithme utilisé est similaire à celui que vous avez mentionné ci-dessus - le tri par fusion externe.

Je peux trier 128 Go de données (chaque élément de 100 octets) en 9 heures sur une seule machine, puis rechercher en binaire les données triées en un rien de temps.

Voici un article sur la façon de rechercher des données volumineuses en utilisant ma grande file d'attente open source et les grandes structures de tableaux.

Bouledogue
la source