J'ai FILE_A qui a plus de 300 000 lignes et FILE_B qui a plus de 30 millions de lignes. J'ai créé un script Bash qui greps chaque ligne dans FILE_A dans FILE_B et écrit le résultat de la grep dans un nouveau fichier.
L'ensemble de ce processus prend plus de 5 heures.
Comment puis-je améliorer les performances de mon script?
J'utilise grep -F -m 1
comme commande grep. FILE_A ressemble à ceci:
123456789
123455321
et FILE_B est comme ceci:
123456789,123456789,730025400149993,
123455321,123455321,730025400126097,
Donc, avec Bash, j'ai une while
boucle qui sélectionne la ligne suivante dans FILE_A et la récupère dans FILE_B. Lorsque le motif se trouve dans FILE_B, je l'écris dans le fichier result.txt.
while read -r line; do
grep -F -m1 $line 30MFile
done < 300KFile
la source
Voici une réponse Perl pour la postérité. Je fais régulièrement cela pour faire correspondre les lignes 1M aux lignes 30-35M. Il faut environ 10 secondes pour terminer.
Tout d'abord, hachez FILE_A:
Ensuite, si votre gros fichier est délimité et savez quelle colonne aller après, vérifiez juste l'existence de la clé de hachage lorsque vous exécutez FILE_B, ce qui est beaucoup, beaucoup plus rapide que de vérifier l'égalité ou la correspondance des expressions régulières:
Si votre fichier cible plus volumineux n'est pas bien analysable, alors ce script perd sa valeur car une grande partie de sa vitesse vient du fait de ne pas avoir à lancer le moteur d' expression régulière .
la source
Si cela ne vous dérange pas d'une programmation plus complexe, envisagez d'utiliser des arborescences de suffixes (ou une variante).
Vous pouvez prétraiter en
FILE_B
utilisant l'algorithme d'Ukkonen en temps linéaire. Ensuite, vous interrogez chaque ligne enFILE_A
temps linéaire en longueur de ligne et obtenez tous les numéros de ligne qui correspondent (peut-être besoin d'adapter l'arbre un peu) que vous pouvez écrire dans un fichier de résultats.L'ensemble de la procédure s'exécute dans le temps O (n + Nm) si n est la longueur de
FILE_B
,N
est le nombre de lignes dansFILE_A
et m est la longueur de la ligne la plus longueFILE_A
- c'est essentiellement un temps d'exécution linéaire. Bat le temps quadratique dont votre approche originale a besoin par ampleur.la source
J'ai trouvé le
--mmap
drapeau récemment, je n'ai pas eu l'occasion de le tester, mais je serai heureux d'entendre vos conclusions. Voici la description de la page de manuel:Voir ceci ou cela pour plus d'informations sur
mmap
.la source
--mmap
dose sans rien vider, je recommanderais une course avec--mmap
et une sans. Et puis utilisezwc
pour voir que vous avez la même quantité de sortie - cela devrait être un test robuste étant donné que nous avons exécuté 2 fois grep, et juste un indicateur différait.pourquoi ne pas mettre ce fichier dans une base de données, les bases de données sont vraiment bonnes pour faire une fusion efficace, un hachage, une jointure en boucle imbriquée comme ceci. Et ils sont vraiment bons pour utiliser la mémoire virtuelle
la source