我一直在尝试过滤键入数据集的不同方法。事实证明,性能可能完全不同。
数据集是基于1.6 GB行数据创建的,该数据包具有33列和4226047行。数据集是通过加载CSV数据并映射到案例类而创建的。
val df = spark.read.csv(csvFile).as[FireIncident]
unitid ='b02'上的过滤器应返回47980行。我测试了以下三种方式:1)使用键入列(本地主机上约500毫秒)
df.where($"UnitID" === "B02").count()
2)使用temp表和sql查询(〜与选项1相同)
df.createOrReplaceTempView("FireIncidentsSF")
spark.sql("SELECT * FROM FireIncidentsSF WHERE UnitID='B02'").count()
3)使用强大的类型类字段(14,987ms,即慢30倍)
df.filter(_.UnitID.orNull == "B02").count()
我再次使用Python API进行了测试,对于相同的数据集,时间为17,046毫秒,与Scala API选项3的性能相当。
df.filter(df['UnitID'] == 'B02').count()
有人可以阐明3)和Python API的执行方式与前两个选项的执行方式不同吗?
这是因为这里的步骤3。
在前两个中,Spark不需要对整个Java/scala对象进行估算 - 它只会查看一列然后移动。
在第三个,由于您使用的是lambda功能,Spark不能说您只想要一个字段,因此它将所有33个字段从每行的内存中拉出,以便您可以检查一个字段。
我不确定为什么第四次这么慢。似乎它的工作方式与第一个相同。
运行Python时发生的事情是首先将代码加载到JVM上,解释,然后最终将其编译到bytecode中。使用Scala API时,Scala在JVM上本身运行,因此您将整个负载Python代码切入JVM部分。