Accès aléatoire aux fichiers compressés?

J’ai un très gros fichier compressé avec gzip assis sur le disque. L’environnement de production est basé sur le “Cloud”, donc les performances de stockage sont terribles, mais le processeur est correct. Auparavant, notre pipeline de traitement de données commençait par gzip -dc diffusant les données sur le disque.

Maintenant, afin de paralléliser le travail, je veux exécuter plusieurs pipelines qui prennent chacun une paire de décalages d’octets – début et fin – et prennent ce morceau du fichier. Avec un fichier simple, cela peut être réalisé avec head et tail , mais je ne sais pas comment le faire efficacement avec un fichier compressé. Si je gzip -dc et que je le gzip -dc en head , les paires de décalage qui sont vers la fin du fichier impliqueront une recherche inutile dans tout le fichier au fur et à mesure de sa décompression.

Donc, ma question concerne l’algorithme gzip – est-il théoriquement possible de rechercher un décalage d’octet dans le fichier sous-jacent ou d’en obtenir une partie arbitraire, sans avoir à décomprimer la totalité du fichier jusqu’à ce point? Si ce n’est pas le cas, comment pourrais-je partitionner efficacement un fichier pour un access «aléatoire» par plusieurs processus tout en minimisant le temps de traitement du débit d’E / S?

Vous ne pouvez pas le faire avec gzip, mais vous pouvez le faire avec bzip2, qui est bloc au lieu de stream – c’est ainsi que le DFS Hadoop divise et parallèle la lecture de fichiers volumineux avec différents mappeurs dans son algorithme MapReduce. Il serait peut-être judicieux de recompresser vos fichiers au format bz2 pour que vous puissiez en tirer parti. ce serait plus facile que certains moyens ad hoc de découper les fichiers.

J’ai trouvé les correctifs qui implémentent cela dans Hadoop, ici: https://issues.apache.org/jira/browse/HADOOP-4012

Voici un autre message sur le sujet: Fichier BZip2 lu dans Hadoop

Peut-être que la navigation dans le code source Hadoop vous donnerait une idée de la manière de lire les fichiers bzip2 par blocs.

Oui, vous pouvez accéder à un fichier gzip de manière aléatoire en lisant la totalité de la séquence une fois et en créant un index. Voir examples / zran.c dans la dissortingbution zlib .

Si vous contrôlez la création du fichier gzip, vous pouvez optimiser le fichier à cette fin en intégrant des points d’entrée à access aléatoire et en construisant l’index lors de la compression.

Vous pouvez également créer un fichier gzip avec des marqueurs en utilisant Z_SYNC_FLUSH suivi de Z_FULL_FLUSH dans zlib ‘s deflate() pour insérer deux marqueurs et rendre le bloc suivant indépendant des données précédentes. Cela réduira la compression, mais pas beaucoup si vous ne le faites pas trop souvent. Par exemple, une fois que chaque mégaoctet aura très peu d’impact. Ensuite, vous pouvez rechercher un marqueur de neuf octets (avec un faux positif beaucoup moins probable que celui de six octets de bzip2): 00 00 ff ff 00 00 00 ff ff .

gzip s’attend à pouvoir diffuser le fichier depuis le début. Vous ne pouvez pas commencer au milieu.

Ce que vous pouvez faire est de diviser le fichier en blocs qui sont compressés par morceaux avec gzip , puis concaténés ensemble. Vous pouvez choisir n’importe quelle taille pour chaque pièce, par exemple 10 Mo ou 100 Mo. Vous décompressez ensuite en commençant au début du morceau contenant le décalage d’octet dont vous avez besoin. En raison d’une fonctionnalité peu connue de gzip (qui consiste à décompresser un fichier qui est la concaténation de plusieurs fichiers gzippés plus petits produit le même résultat que la décompression de chacun des fichiers plus petits et à concaténer le résultat), le fichier volumineux compressé fonctionnera également avec gzip -d / gunzip standard si vous téléchargez le tout.

La partie délicate: vous devez conserver un index contenant le décalage d’octet du début de chaque élément compressé dans le fichier volumineux.