- Expérience comparative des performances de Polars, DuckDB, Daft et Spark pour traiter 650 Go de données Delta Lake stockées sur S3 dans un environnement à nœud unique
- Vérification de la capacité de chaque moteur à traiter des données volumineuses sur une instance EC2 dotée de 32 Go de mémoire, avec exploration du potentiel du nœud unique face à Spark en cluster
- DuckDB a mis 16 minutes, Polars 12 minutes, Daft 50 minutes et PySpark plus d’une heure, confirmant la faisabilité pratique du traitement même sur un nœud unique
- Polars ne prend pas en charge les Deletion Vectors, tandis que seul DuckDB prend en charge cette fonctionnalité, ce qui crée une différence en matière de compatibilité Lake House
- En conclusion, les frameworks à nœud unique démontrent qu’il est possible de traiter de grands volumes de données même sur du matériel peu coûteux, ce qui invite à réévaluer la dépendance au calcul distribué
Fatigue des clusters et alternative en nœud unique
- L’augmentation du coût et de la complexité d’exploitation des clusters Lake House basés sur des SaaS conduit à évoquer un phénomène de « fatigue des clusters (cluster fatigue) »
- Par le passé, faute d’alternative à Pandas, Spark s’imposait, mais l’arrivée de DuckDB, Polars et Daft (D.P.D.) élargit les possibilités de traitement sur un seul nœud
- D.P.D. permet de traiter des jeux de données plus grands que la mémoire (LTM) avec des calculs rapides
- L’article présente deux options, distribuée et non distribuée, et met en avant le concept de « Single Node Rebellion »
Configuration de l’environnement de test
- Création d’une table Delta Lake sur S3 pour y stocker environ 650 Go de données (l’objectif initial était 1 To, mais il a été interrompu)
- Exécution de DuckDB, Polars et Daft sur une instance EC2 (32 Go de RAM, 16 CPU), puis comparaison avec Spark
- Les données sont des données simulées sous forme de publications sur les réseaux sociaux : des dictionnaires Python sont générés, convertis en DataFrame Daft, puis enregistrés en fichiers Parquet
- Les fichiers Parquet sont ensuite convertis en table Delta Lake dans Databricks, avec un partitionnement par année et par mois
- En excluant le log Delta, le volume de données est d’environ 650 Go
Contraintes mémoire et besoin de streaming
- Comme il faut traiter 650 Go de données sur un nœud unique doté de 32 Go de mémoire, la nécessité d’exécuter les requêtes en mode streaming est soulignée
- En citant une issue GitHub de Polars, l’article mentionne des demandes pour une fonction d’écriture en streaming vers Iceberg
- Il insiste sur la nécessité pour les frameworks modernes comme Polars et DuckDB de proposer une prise en charge native de la lecture et de l’écriture en streaming pour les formats Lake House
Résultats des tests par moteur
- DuckDB
- Seul à prendre en charge les Deletion Vectors
- A réussi à traiter 650 Go de données en 16 minutes sur une machine Linux avec 32 Go de RAM
- Code simple et fichier de sortie généré correctement
- Polars
- Ne prend pas en charge les Deletion Vectors, ce qui limite son usage dans un environnement Lake House
- Nécessite l’utilisation de la Lazy API (Scan/Sink)
- Traitement terminé en 12 minutes, plus rapide que DuckDB
- Daft
- Basé sur Rust, agréable à utiliser, mais avec 50 minutes de traitement, c’est le plus lent
- Fonctionnement stable confirmé sur des tâches liées à Iceberg
- PySpark (Databricks Single Node)
- Plus d’une heure d’exécution, sans tuning
- Efficacité inférieure à celle des moteurs à nœud unique
- L’objectif de l’expérience était moins la vitesse que la validation de la faisabilité du nœud unique
Conclusion et enseignements
- L’expérience montre que les frameworks à nœud unique peuvent traiter de gros volumes de données Lake House
- Même sur du matériel peu coûteux, il est possible d’obtenir des temps d’exécution raisonnables et une structure de code simple
- DuckDB, Polars et Daft offrent tous des performances exploitables sans cluster distribué
- Cela montre que le calcul distribué n’est pas l’unique solution, et invite à repenser l’architecture Lake House moderne
- Le concept de « Single Node Rebellion » met en lumière la possibilité d’une approche de la data engineering plus économique
1 commentaires
Commentaires Hacker News
Daft est un moteur de traitement de données haute performance pour les workloads d’IA, qui fonctionne aussi bien sur un nœud unique qu’en environnement distribué
Ce benchmark nous a permis d’identifier de nombreuses pistes d’amélioration en matière de parallélisme et de pipelining. Il y avait notamment beaucoup à optimiser dans le lecteur deltalake et l’opérateur groupby
Nous prévoyons d’intégrer ces améliorations dans de prochaines releases, et davantage de détails sont disponibles sur GitHub, Twitter, LinkedIn
Si Daft vous intéresse, vous pouvez l’essayer directement avec
pip install daftAu lieu d’un outillage excessif, il suffit d’utiliser les outils GNU
À noter, c’est un vieil article mais il reste intéressant — command-line tools can be 235x faster than your Hadoop cluster
Si on agrège 650GB de données JSON avec des outils CLI, il est difficile de rivaliser avec les performances de traitement parallèle de DuckDB ou ClickHouse. J’ai aussi essayé avec GNU Parallel, mais il y avait des limites
En pratique, il faut un catalogue de données et du travail basé sur un cluster
Je requête directement des fichiers Parquet au lieu d’utiliser Delta ou Iceberg
Je récupère les résultats de requêtes BigQuery en fichiers Parquet locaux (environ 1GB chacun), puis je les analyse avec DuckDB. Les données sont bien plus grosses que la RAM, mais ça fonctionne très bien
Je compare aussi la différence de performance d’agrégation entre BigQuery et DuckDB, et j’exécute parfois les tâches en les répartissant entre les deux moteurs. Ce genre de combinaison est l’un des aspects amusants du data engineering
Avec un débit maximal de 10Gbps sur une instance c5.4xlarge, il faut au minimum 9 minutes pour lire 650GB depuis S3
De petites différences dans la manière de planifier les I/O ont probablement eu un fort impact sur les résultats
Il pourrait même être plus économique d’utiliser une instance plus grosse pour terminer plus vite
Le stockage NVMe est bien plus rapide que S3, et un CPU local de 8 à 16 cœurs pourrait faire mieux que le cloud
S3 est un excellent produit, mais il n’arrive pas au niveau des performances du stockage local
La distribution des tailles de fichiers ou le skew des appels API ont sans doute été des variables plus importantes
Je suis tout à fait d’accord avec l’idée qu’« une grosse instance pourrait au final coûter moins cher »
Spark est adapté aux grands datasets multi-étapes et, quand S3 sert de backend, le goulot d’étranglement réseau apparaît dans les coûts
Les performances sur un seul nœud de DuckDB/Polars sont impressionnantes, mais c’est un peu comme faire courir un avion sur la piste contre une moto
Ce genre de différence explique aussi pourquoi tant de gens se fatiguent du calcul distribué
Si l’on identifie les limites de ressources et qu’on exprime les performances réelles en proportion de ces limites, tout devient beaucoup plus clair
C’est bien d’avoir essayé différents systèmes, mais j’aimerais qu’on traite sérieusement les requêtes plus grandes que la mémoire
DuckDB est solide sur le streaming hors mémoire, mais Polars est encore immature sur ce point
La configuration par défaut de S3 n’empêche pas les lectures parallèles, donc le goulot d’étranglement est probablement au niveau de la bande passante réseau de la VM
ClickHouse était le plus rapide, et DuckDB était le meilleur en termes de simplicité et de stabilité
Flink et PySpark étaient 3 à 5 fois plus lents, et Dask comme Ray étaient aussi trop lents
Maintenant, je recommande de commencer avec DuckDB ou ClickHouse pour la plupart des workloads. Quand Pandas est trop lent, ma stratégie par défaut est de le remplacer par DuckDB
Même avec une bibliothèque single-node, on peut gérer sans problème autour de 1TB, et il suffit de passer à Spark au-delà de 10TB
Issue associée
Mais il est souvent possible de résoudre le problème avec de meilleurs outils
Autrefois, un ingénieur junior avait mis 18 heures à traiter plusieurs centaines de fichiers JSON de 5GB en concaténant des chaînes Python,
puis on est passé à de simples outils console et au multiprocessing, et on est tombés à 35 minutes
L’essentiel, c’est de choisir le bon outil
Les coûts de maintenance et d’exécution sont très faibles, et c’est un outil avec un excellent rapport qualité-prix
Pour résoudre le problème du trop grand nombre de fichiers Parquet lors de petites écritures par lots, DuckLake les stocke inline dans un SGBD (comme Postgres)
La possibilité de les réécrire en Parquet n’est apparue que récemment, et il faut encore stabiliser cela
Documentation associée
Il faut représenter le catalogue dans une base SQL, alors que l’intérêt de Parquet est justement d’éviter cette complexité
Si le catalogue était lui aussi basé sur Parquet, on pourrait avoir un format auto-amorçable