Optimiser le traitement de gros fichiers CSV : streaming, chunking, compression et alternatives
Optimiser le traitement de gros fichiers CSV : streaming, chunking, compression et alternatives
Un fichier CSV de 50 Mo s'ouvre en quelques secondes. Un fichier de 5 Go fait planter Excel, sature la RAM et bloque votre machine pendant de longues minutes. Avec l'explosion des volumes de données, savoir traiter efficacement de gros fichiers CSV est devenu une compétence indispensable. Ce guide passe en revue les techniques d'optimisation, les outils modernes et les alternatives au CSV pour le traitement de données volumineuses.
Comprendre le problème : pourquoi les gros CSV posent problème
Le piège de la lecture intégrale
La plupart des outils (Excel, Google Sheets, pandas avec pd.read_csv() par défaut) chargent l'intégralité du fichier en mémoire avant de commencer le moindre traitement. Pour un fichier de 2 Go, cela signifie au minimum 2 Go de RAM consommés, souvent davantage car les données texte sont converties en objets Python ou en structures internes plus volumineuses.
Concrètement, un fichier CSV de 2 Go contenant des transactions financières peut occuper 6 à 8 Go de RAM une fois chargé dans un DataFrame pandas. Si votre machine dispose de 8 Go de RAM, le système commence à utiliser le swap disque, les performances s'effondrent et le traitement qui devrait prendre 30 secondes dure 20 minutes.
Les limites des outils classiques
- Excel : limité à 1 048 576 lignes. Au-delà, les données sont tronquées silencieusement.
- Google Sheets : limité à 10 millions de cellules. Un fichier de 100 colonnes est plafonné à 100 000 lignes.
- pandas (mode par défaut) : charge tout en RAM. Inutilisable au-delà de quelques centaines de Mo sans optimisation.
Pour des fichiers de taille raisonnable (jusqu'à quelques dizaines de Mo), un viewer CSV en ligne permet une visualisation rapide et fluide directement dans le navigateur.
Technique 1 : le chunking (lecture par blocs)
Le chunking consiste à lire le fichier par morceaux de taille fixe, traiter chaque morceau indépendamment, puis combiner les résultats. C'est la technique la plus accessible.
Avec pandas
python
import pandas as pd
resultats = []
for chunk in pd.read_csv('transactions.csv', chunksize=50000):
# Filtrer les transactions supérieures à 1000 EUR
filtre = chunk[chunk['montant'] > 1000]
resultats.append(filtre)
df_final = pd.concat(resultats)
print(f"{len(df_final)} transactions > 1000 EUR")
Avec un chunksize de 50 000 lignes, seules 50 000 lignes sont en mémoire à un instant donné, quelle que soit la taille totale du fichier. La consommation mémoire reste constante.
Quand utiliser le chunking
- Fichiers de 500 Mo à quelques Go
- Opérations ligne par ligne (filtrage, transformation, agrégation simple)
- Environnement avec RAM limitée
- Pas besoin de jointures entre les blocs
Limites du chunking
Le chunking ne convient pas aux opérations qui nécessitent une vue globale des données : tri de l'ensemble du fichier, calcul de médiane, déduplication globale. Pour ces cas, il faut des outils conçus pour le traitement out-of-core.
Technique 2 : le streaming
Le streaming va plus loin que le chunking : chaque ligne est lue et traitée individuellement, sans jamais stocker plus d'une ligne en mémoire.
Avec le module csv de Python
python
import csv
total = 0
count = 0
with open('transactions.csv', 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
montant = float(row['montant'])
if montant > 1000:
total += montant
count += 1
print(f"{count} transactions, total: {total:.2f} EUR")
Cette approche consomme quelques Ko de RAM, quelle que soit la taille du fichier. Elle est idéale pour des comptages, des sommes ou des filtrages simples.
Avec csvkit en ligne de commande
csvkit est une suite d'outils en ligne de commande spécialisée dans le traitement CSV :
bash
Filtrer les lignes où le montant > 1000
csvgrep -c montant -r "^[1-9][0-9]{3,}" transactions.csv > grosses_transactions.csv
Statistiques descriptives
csvstat transactions.csv
Sélectionner des colonnes
csvcut -c nom,montant,date transactions.csv
csvkit utilise le streaming par défaut et peut traiter des fichiers de plusieurs Go sans problème de mémoire.
Technique 3 : l'optimisation des types de données
Une optimisation souvent négligée : spécifier les types de données à la lecture. Par défaut, pandas infère les types, ce qui est coûteux en mémoire.
python
import pandas as pd
dtypes = {
'id': 'int32', # au lieu de int64 (50% de RAM en moins)
'categorie': 'category', # au lieu de object (90% de RAM en moins pour les champs répétitifs)
'montant': 'float32', # au lieu de float64
'code_postal': 'str' # empêche la conversion en nombre
}
df = pd.read_csv('transactions.csv', dtype=dtypes)
Sur un fichier de 1 Go, cette optimisation peut réduire la consommation mémoire de 60 à 70 %. Le type category est particulièrement efficace pour les colonnes avec peu de valeurs distinctes (pays, catégorie, statut).
Technique 4 : les outils nouvelle génération
Polars : le successeur de pandas
Polars, écrit en Rust, est conçu pour la performance. Il est en moyenne 3 à 10 fois plus rapide que pandas sur les opérations courantes et consomme significativement moins de mémoire.
python
import polars as pl
Lecture lazy : rien n'est chargé en mémoire
df = pl.scan_csv('transactions.csv')
Définir les transformations
resultat = (
df
.filter(pl.col('montant') > 1000)
.group_by('categorie')
.agg([
pl.col('montant').sum().alias('total'),
pl.col('montant').count().alias('nombre')
])
.sort('total', descending=True)
.collect() # Exécution effective ici
)
print(resultat)
Le mode scan_csv (lazy evaluation) ne charge que les données nécessaires au résultat final. Si vous filtrez 1 % des lignes, seul 1 % est effectivement lu en mémoire.
DuckDB : SQL sur vos fichiers CSV
DuckDB est une base de données analytique embarquée qui permet d'exécuter du SQL directement sur des fichiers CSV, sans les charger en mémoire.
python
import duckdb
Requête SQL directement sur le fichier CSV
resultat = duckdb.sql("""
SELECT categorie,
SUM(montant) as total,
COUNT(*) as nombre
FROM 'transactions.csv'
WHERE montant > 1000
GROUP BY categorie
ORDER BY total DESC
""")
print(resultat.fetchdf())
DuckDB excelle sur les fichiers de plusieurs Go. Il utilise le traitement vectorisé et la parallélisation automatique. Un fichier de 10 Go peut être agrégé en quelques secondes.
Benchmarks comparatifs
Sur un fichier CSV de 5 Go (50 millions de lignes, 12 colonnes) avec une opération de filtrage + agrégation :
| Outil | Temps | RAM utilisée |
|---|---|---|
| pandas (défaut) | 4 min 30 s | 14 Go |
| pandas (chunking) | 2 min 15 s | 800 Mo |
| Polars (lazy) | 18 s | 1.2 Go |
| DuckDB | 12 s | 600 Mo |
Ces chiffres varient selon le matériel et la nature des données, mais l'ordre de grandeur est représentatif.
Technique 5 : la compression
Compresser vos fichiers CSV réduit l'espace disque et accélère la lecture (moins de données à lire depuis le disque).
Formats de compression courants
- gzip : le plus répandu. Un fichier CSV de 1 Go compressé en gzip pèse typiquement 150 à 300 Mo. pandas, Polars et DuckDB lisent les fichiers
.csv.gznativement.
- zstd (Zstandard) : meilleur ratio compression/vitesse que gzip. Supporté par Polars et DuckDB.
- lz4 : compression très rapide, ratio moindre. Idéal quand la vitesse prime sur la taille.
python
Lecture directe d'un CSV compressé en gzip
import pandas as pd
df = pd.read_csv('transactions.csv.gz', compression='gzip')
Avec Polars
import polars as pl
df = pl.read_csv('transactions.csv.gz')
Les alternatives au CSV pour les gros volumes
Parquet : le format analytique de référence
Pour le stockage et le traitement de gros volumes, le format Parquet surpasse le CSV sur tous les critères de performance :
- Stockage colonnaire : seules les colonnes nécessaires sont lues. Si vous n'avez besoin que de 3 colonnes sur 50, le gain est considérable.
- Compression intégrée : compression par colonne avec Snappy, Zstd ou Gzip. Un fichier Parquet est 3 à 5 fois plus petit qu'un CSV équivalent.
- Typage : les types de données sont définis dans le schéma, pas d'inférence coûteuse à la lecture.
- Partitionnement : les données peuvent être réparties en sous-dossiers par date, catégorie, etc.
python
Conversion CSV vers Parquet
import polars as pl
df = pl.read_csv('transactions.csv')
df.write_parquet('transactions.parquet', compression='zstd')
Lecture Parquet (10x plus rapide que CSV)
df = pl.read_parquet('transactions.parquet')
Pour l'échange avec des collègues non techniques qui ont besoin d'ouvrir le fichier dans Excel, le CSV reste nécessaire. Utilisez le convertisseur de csv-viewer.online pour passer d'Excel à CSV et inversement.
Apache Arrow / Feather
Format binaire optimisé pour les échanges entre processus et langages (Python, R, Julia). Lecture quasi instantanée, mais fichiers plus volumineux que Parquet.
Recommandations pratiques par taille de fichier
Moins de 100 Mo
Utilisez pandas normalement ou visualisez directement dans csv-viewer.online. Pas besoin d'optimisation particulière. Vous pouvez générer des graphiques directement depuis le navigateur.
100 Mo à 1 Go
Optimisez les types de données avec pandas, ou passez à Polars pour un gain de performance immédiat. Le chunking est une option si vous restez sur pandas.
1 Go à 10 Go
Polars en mode lazy ou DuckDB sont les choix optimaux. Considérez la conversion en Parquet si vous allez relire le fichier plusieurs fois.
Plus de 10 Go
DuckDB pour les requêtes SQL, Polars avec streaming pour les transformations. Convertissez systématiquement en Parquet. Envisagez le partitionnement si les données s'y prêtent (par date, par région). Pour les volumes supérieurs à 100 Go, passez à des solutions distribuées (Spark, Dask).
Créer des fichiers CSV optimisés dès le départ
Si vous produisez des fichiers CSV destinés à être traités par d'autres, quelques bonnes pratiques réduisent les problèmes en aval :
- Utilisez le créateur CSV pour définir une structure propre avec des en-têtes explicites
- Privilégiez l'UTF-8 comme encodage
- Utilisez des types cohérents : pas de mélange nombres/texte dans une même colonne
- Évitez les colonnes inutiles qui alourdissent le fichier
- Documentez le schéma (colonnes, types, unités) dans un fichier d'accompagnement
Conclusion
Le traitement de gros fichiers CSV n'est plus un problème insurmontable. Les outils modernes comme Polars et DuckDB offrent des performances remarquables avec une consommation mémoire maîtrisée. La clé est d'adapter votre stratégie à la taille de vos données : pandas optimisé pour les fichiers modérés, Polars ou DuckDB pour les volumes importants, et conversion en Parquet pour les traitements récurrents. Quelle que soit l'approche, commencez toujours par comprendre vos données avant de les traiter.