Scala ou PySpark : lequel choisir pour Spark ?

On répète que Scala est plus rapide que PySpark. C’est vrai dans un cas précis et faux ailleurs. Ce qui se passe sous le capot, et comment choisir.

6 min de lecturesparkscalapysparkpythonbig-data

« Scala est plus rapide que PySpark. » La phrase est répétée dans tous les forums, elle décide de carrières et de choix d’architecture — et elle est fausse dans la majorité des cas tels qu’on écrit Spark aujourd’hui. Elle était vraie en 2015. Depuis, l’essentiel du travail a migré vers un endroit où le langage n’a plus d’influence.

Voici ce qui se passe réellement sous le capot, les trois situations où l’écart existe pour de bon, et comment choisir sans se laisser guider par un slogan.

Ce que Spark exécute vraiment

Spark tourne sur la JVM. Il n’existe pas de version Python de son moteur. Ce que fait PySpark, c’est piloter cette JVM depuis Python via une passerelle appelée Py4J :

Point crucial : quand vous écrivez df.filter(...).groupBy(...).agg(...) en Python, aucune donnée ne passe par Python. Votre code Python construit un plan logique, l’envoie à la JVM, et c’est Catalyst qui l’optimise puis l’exécute — exactement le même code que celui déclenché depuis Scala.

Autrement dit : sur l’API DataFrame, Scala et PySpark ont des performances quasi identiques. Le langage sert à décrire l’intention ; l’exécution est la même.

Les trois cas où l’écart existe pour de bon

1. Les UDF Python

C’est là que le mythe trouve son origine, et il est parfaitement justifié :

python
# Chaque ligne : JVM → sérialisation → processus Python → retour → JVM
@udf("string")
def traiter(s):
    return s.upper()

Une UDF Python force un aller-retour hors de la JVM, ligne par ligne. Le surcoût est massif — on parle couramment d’un facteur 10 à 100 par rapport à l’équivalent natif.

La parade existe depuis Spark 2.3 : pandas_udf, qui transfère des lots via Apache Arrow en format colonnaire.

python
from pyspark.sql.functions import pandas_udf
import pandas as pd

@pandas_udf("double")
def normaliser(s: pd.Series) -> pd.Series:
    return (s - s.mean()) / s.std()

La sérialisation est amortie sur des milliers de lignes et le calcul est vectorisé. On revient dans un ordre de grandeur raisonnable. Le détail du mécanisme — et pourquoi une UDF reste une boîte noire même en Scala — est dans pourquoi votre UDF est dix fois plus lente.

2. L’API RDD

Un rdd.map(lambda x: ...) en Python manipule de vrais objets Python sur les exécuteurs, avec sérialisation Pickle à chaque étape. Là, l’écart avec Scala est réel et structurel.

C’est un argument de moins qu’il n’y paraît : en 2026, écrire du RDD est déjà rarement le bon choix, dans les deux langages. Si votre pipeline est en DataFrame, ce point ne vous concerne pas.

3. La logique côté driver

Des boucles Python qui appellent Spark des milliers de fois paient le coût de Py4J à chaque appel. Sur un pipeline qui génère dynamiquement des centaines de requêtes, ça se sent.

Symétriquement : un job qui lance dix actions sur des téraoctets ne verra jamais la différence — le temps est passé dans le cluster, pas dans la passerelle.

Le tableau de décision honnête

CritèreScalaPySpark
Performance API DataFrameIdentiqueIdentique
Performance UDFBonneMauvaise (correcte avec pandas_udf)
Performance API RDDBonneDégradée
Écosystème data scienceLimitéImmense (pandas, scikit-learn, PyTorch, MLflow)
Sécurité de typesÀ la compilationÀ l’exécution
Vitesse de prototypageMoyenneÉlevée
Notebooks (Jupyter, Databricks)CorrectNatif
Bassin de recrutementÉtroitLarge
Accès aux internes de SparkDirectPartiel
Nouvelles API SparkEn premierAvec un décalage
Courbe d’apprentissageRaideDouce
Débogage des erreursTraces JVM lisiblesTraces Py4J souvent obscures

Comment choisir, concrètement

PySpark si vous venez de la data science ou de l’analyse ; votre équipe écrit déjà du Python ; vous travaillez en notebooks ; vous devez brancher Spark sur du machine learning (scikit-learn, XGBoost, MLflow, PyTorch) ; vous prototypez et l’itération rapide compte plus que la milliseconde.

Scala si vous construisez une plateforme de données — des bibliothèques, des frameworks internes, du code réutilisé par plusieurs équipes ; vous avez besoin de la sécurité de types sur des pipelines critiques ; vous écrivez des sources de données, des extensions Catalyst, des connecteurs ; vous êtes déjà dans un écosystème JVM (Kafka, Flink, Akka).

Les deux si votre organisation le supporte : c’est le cas fréquent dans les grandes équipes data — Scala pour la couche d’ingestion et les bibliothèques partagées, PySpark pour l’exploration et le machine learning.

Et pour apprendre Spark, lequel prendre en premier ?

Python, dans la grande majorité des cas — pour une raison pédagogique : vous voulez apprendre Spark, pas vous battre simultanément avec la JVM, sbt, les implicits Scala et les types supérieurs. PySpark laisse toute l’attention sur les concepts qui comptent (partitions, shuffle, lazy evaluation, plans d’exécution), qui sont identiques dans les deux langages.

Une fois ces concepts acquis, passer à Scala prend quelques jours : l’API DataFrame est la même à la syntaxe près. L’inverse — apprendre Scala d’abord — coûte des semaines avant d’écrire son premier job utile.

L’exception : si votre équipe est déjà entièrement en Scala, commencez en Scala. Le coût de l’apprentissage est inférieur à celui d’écrire du code que personne ne pourra maintenir.

Ce que le choix ne change pas

C’est le point le plus utile de cet article. Quel que soit le langage, vous devrez comprendre exactement les mêmes choses :

Aucun de ces sujets ne dépend du langage. C’est là que se trouvent les facteurs 10 sur les temps d’exécution — pas dans le choix Scala/Python. Un développeur PySpark qui maîtrise le shuffle écrira des jobs bien plus rapides qu’un développeur Scala qui l’ignore.

Ce qu’il faut retenir

Le débat « Scala ou PySpark » est largement mal posé. Sur l’API DataFrame — c’est-à-dire sur la façon dont on écrit Spark aujourd’hui — les deux langages produisent le même plan et la même exécution. L’écart réel se concentre sur les UDF Python, l’API RDD et la logique côté driver : trois zones qu’on peut souvent contourner (pandas_udf, passage au DataFrame, réduction des allers-retours).

Choisissez donc sur les vrais critères : l’écosystème dont vous avez besoin, les compétences de votre équipe, la nature du code que vous produisez. Et investissez le temps gagné sur ce qui fait vraiment la différence — la compréhension du moteur, identique dans les deux langages.

Ce sujet fait partie d’un cours complet

Développement et déploiement de solutions de données — les premiers modules sont en accès libre.

Voir le plan du cours

Continuer sur le même sujet