J'ai expérimenté différentes manières de filtrer un ensemble de données typé. Il s'avère que la performance peut être très différente.
L'ensemble de données a été créé sur la base de 1,6 Go de données, avec 33 colonnes et 4226047 lignes. DataSet est créé en chargeant des données csv et mappé à une classe de cas.
val df = spark.read.csv(csvFile).as[FireIncident]
Un filtre sur UnitId = 'B02' devrait retourner 47980 lignes. J'ai testé trois manières comme ci-dessous: 1) Utiliser la colonne dactylographiée (~ 500 ms sur l'hôte local)
df.where($"UnitID" === "B02").count()
2) Utiliser la table temporaire et la requête SQL (~ identique à l’option 1)
df.createOrReplaceTempView("FireIncidentsSF")
spark.sql("SELECT * FROM FireIncidentsSF WHERE UnitID='B02'").count()
3) Utilisez un champ de classe typé fort (14 987 ms, soit 30 fois plus lent)
df.filter(_.UnitID.orNull == "B02").count()
Je l'ai testé à nouveau avec l'API python. Pour le même ensemble de données, le délai est de 17,046 ms, ce qui est comparable aux performances de l'option 3 de l'API scala.
df.filter(df['UnitID'] == 'B02').count()
Quelqu'un pourrait-il expliquer comment 3) et les API Python sont exécutés différemment des deux premières options?
C'est à cause de l'étape 3 ici .
Dans les deux premiers cas, spark n'a pas besoin de désérialiser tout l'objet Java/Scala; il se contente de regarder la colonne et de passer à la suite.
Dans la troisième, depuis que vous utilisez une fonction lambda, spark ne peut pas dire que vous voulez juste un champ, alors il extrait les 33 champs de la mémoire pour chaque ligne, de sorte que vous puissiez vérifier le champ.
Je ne sais pas pourquoi la quatrième est si lente. Il semble que cela fonctionnerait de la même manière que le premier.
Lors de l'exécution de python, votre code est d'abord chargé sur la machine virtuelle Java, interprété, puis finalement compilé en bytecode. Lorsque vous utilisez l'API Scala, Scala s'exécute en mode natif sur la machine virtuelle Java, ce qui vous permet de supprimer tout le code de chargement python dans la partie JVM.