Technique de fusion et de compression performante pour les fichiers .jsonl.gz avec Polars

Lors du traitement de DataFrames de grande taille (par exemple, plus de 130 000 lignes de texte et de métadonnées), la fusion efficace des données et leur sauvegarde sous format compressé représente un défi fréquent en ingénierie des données. Ce guide technique décrit une approche complète pour combiner des données à l'aide de Polars et les exporter au format .jsonl.gz en optimisant les performances.

Définition du scénario

  • Objectif : Intégrer les étiquettes de sujet (final_subjects) et les cartographies de probabilité (final_result_map) provenant de df_subject dans la table principale df_text.
  • Caractéristiques des données : Incluent du texte étendu (text), des listes (list[str]) et des chaînes structurées au format JSON.
  • Exigences de sortie : Exporter en format JSON ligneparligne (JSONL) avec une compression Gzip.

Optimisation de la fusion avec l'opération Join

L'opération join de Polars, implémentée en Rust, offre des performances nettement supérieures à celles de Pandas.

import polars as pl

# Approche recommandée : sélectionner les colonnes nécessaires en amont pour éviter les suffixes de noms dupliqués (comme _right)
resultat_fusion = donnees_texte.join(
    donnees_matiere.select(["identifiant", "sujets_finaux", "carte_resultats"]),
    on="identifiant",
    how="left"
)

Remarque : Après la fusion de données massives et fragmentées, il est conseillé d'exécuter resultat_fusion.rechunk(). Cette opération réorganise la mémoire pour rendre les données contiguës, ce qui améliore la vitesse de sérialisation ultérieure.

Problèmes rencontrés avec write_ndjson

En essayant de sauvegarder directement avec compression, plusieurs obstacles apparaisent :

  1. Paramètre absent : La fonction write_ndjson() de Polars ne prend pas en charge nativement le paramètre compression="gzip", contrairement à write_csv(). Tenter de l'utiliser génère une erreur de type TypeError.
  2. Performance limitée de la bibliothèque standard : Utiliser le module Python intégré gzip (comme gzip.open) avec Polars permet de compresser, mais en raison de son exécution monothread et des passes par les E/S Python, le processus devient extrêmement lent.
  3. Impact du niveau de compression : Le module gzip par défaut utilise compresslevel=9, ce qui sollicite énormément le CPU et réduit drastiquement la vitesse d'écriture.

Solution performante : intégration de la bibliothèque isal

Pour surmonter les limitations des outils Python standard, il est recommandé d'utiliser la bibliothèque Intel Storage Acceleration Library (ISA-L) via son wrapper Python isal.

Implémentation pratique :

  1. Installation : pip install isal

  2. Exemple de code : ``` from isal import igzip

    def compresser_et_sauvegarder_jsonl(df: pl.DataFrame, chemin_fichier: str): # Utiliser igzip pour une compression à haute vitesse # compresslevel=1 ou 2 offre un excellent compromis entre rapidité et taux de compression with igzip.open(chemin_fichier, "wb", compresslevel=2) as fichier_sortie: df.write_ndjson(fichier_sortie)

    
    

Pourquoi isal.igzip surpasse-t-il les autres méthodes ?

  • Optimisations matérielles : isal exploite des instructions assembleur optimisées pour les processeurs modernes (comme les pipelines multiniveaux), atteignant des vitesses 5 à 10 fois supérieures à celles du module gzip standard à taux de compression équivalent.
  • Écriture par flux : La méthode write_ndjson de Polars accepte tout objet fichier possédant une méthode .write(). En connectant l'objet igzip à Polars, les données s'écoulent directement de la mémoire vers le moteur de compression, éliminant ainsi la nécessité de fichiers intermédiaires volumineux.

Pistes d'amélioration avancées

  • Paramétrage du niveau de compression : Pour les fichiers .jsonl.gz, un compresslevel entre 1 et 3 représente généralement le meilleur rapport efficacité/coût. Des niveaux plus élevés augmentent de manière exponentielle la charge CPU tout en réduisant marginalement la taille du fichier.
  • Lecture automatisée : La fonction read_ndjson() de Polars détecte intelligemment les en-têtes. Ainsi, même pour les fichiers compressés avec isal, l'utilisation de pl.read_ndjson("fichier.jsonl.gz") permet une décompression et une lecture automatiques sans intervention supplémentaire.
  • Format alternatif recommandé : Si l'environnement en aval le permet, le format Parquet (df.write_parquet(..., compression="zstd")) est le format natif privilégié de Polars, offrant de meilleurs taux de compression et des performances de lecture/écriture supérieures au format JSONL.

Étiquettes: Polars JSONL gzip isal Parquet

Publié le 14 juin à 22h40