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.
la source
Réponses:
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.
la source
La fusion externe de R-Way comme dans la
sort
commande 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.la source
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:
la source
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 .
la source
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.
la source
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.
la source
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.
la source