web-dev-qa-db-fra.com

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

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 les lecteurs de bande .

Je pense que c'est une bonne solution (avec une complexité O (n x 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.

[~ # ~] modifier [~ # ~]

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

  • Les données doivent être triées périodiquement, par ex. 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 n'est 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 à l'esprit é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.

12
Giorgio

La référence canonique sur le tri et la recherche est Knuth, Vol. . 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.

13
John R. Strohm

Fusion R-Way externe comme dans la commande UNIX sort 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 "merge sort", et si vous ne le connaissez pas, jetez un œil.

6
thiton

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 deuxième, 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 exécutez 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 BEAUCOUP (ce 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 videront directement un fichier?
  • Format de fichier? (Texte? Enregistrement fixe?)
  • Y a-t-il d'autres circonstances spéciales dont je n'ai pas parlé?
4
Bill K

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 .

3
m3th0dman

Vous pourriez être intéressé par un tri par sea . 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.

1
stonemetal

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

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) :-)
0
malejpavouk

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 - 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.

Ici est un article sur la recherche de données volumineuses en utilisant ma grande file d'attente open source et les grandes structures de tableaux.

0
Bulldog