wake-up-neo.com

Spark DataSet-Filterleistung

Ich habe verschiedene Möglichkeiten ausprobiert, um einen typisierten Datensatz zu filtern. Es stellt sich heraus, dass die Leistung sehr unterschiedlich sein kann. 

Der Datensatz wurde basierend auf 1,6 GB Datenzeilen mit 33 Spalten und 4226047 Zeilen erstellt. DataSet wird durch Laden von CSV-Daten erstellt und einer Fallklasse zugeordnet. 

val df = spark.read.csv(csvFile).as[FireIncident]

Ein Filter für UnitId = 'B02' sollte 47980 Zeilen zurückgeben. Ich habe drei Möglichkeiten wie folgt getestet: 1) Verwenden Sie eine typisierte Spalte (~ 500 ms auf dem lokalen Host).

df.where($"UnitID" === "B02").count()

2) Verwenden Sie temporäre Tabelle und SQL-Abfrage (~ wie bei Option 1).

df.createOrReplaceTempView("FireIncidentsSF")
spark.sql("SELECT * FROM FireIncidentsSF WHERE UnitID='B02'").count()

3) Verwenden Sie ein stark typisiertes Klassenfeld (14.987ms, d. H. 30 Mal langsamer).

df.filter(_.UnitID.orNull == "B02").count()

Ich habe es erneut mit der Python-API getestet, für den gleichen Datensatz ist das Timing 17.046 ms, vergleichbar mit der Leistung der Scala-API-Option 3. 

df.filter(df['UnitID'] == 'B02').count()

Könnte jemand ein wenig Licht darauf werfen, wie 3) und die Python-API anders als die ersten beiden Optionen ausgeführt werden? 

7
YPL

Es ist wegen Schritt 3 hier .

In den ersten beiden Fällen muss Spark nicht das gesamte Java/Scala-Objekt deserialisieren. Es betrachtet nur die eine Spalte und bewegt sich weiter.

Im dritten Fall kann Spark aufgrund der Verwendung einer Lambda-Funktion nicht erkennen, dass Sie nur das eine Feld benötigen. Es zieht also alle 33 Felder für jede Zeile aus dem Speicher, sodass Sie das eine Feld überprüfen können.

Ich bin mir nicht sicher, warum der vierte so langsam ist. Es scheint, als würde es genauso funktionieren wie beim ersten. 

8
Corey Woodfield

Beim Ausführen von Python wird der Code zuerst in die JVM geladen, interpretiert und anschließend in Bytecode kompiliert. Bei Verwendung der Scala-API wird Scala nativ in der JVM ausgeführt, sodass Sie den gesamten Python-Code zum Laden in den JVM-Teil ausschneiden. 

0
TheM00s3