我对DataFram API cache
的用法有疑问。考虑以下查询:
val dfA = spark.table(tablename)
.cache
val dfC = dfA
.join(dfA.groupBy($"day").count,Seq("day"),"left")
因此dfA
在此查询中使用了两次,因此我认为将其缓存是有益的。但是我对该计划感到困惑,该表仍然被扫描了两次(FileScan
出现了两次):
dfC.explain
== Physical Plan ==
*Project [day#8232, i#8233, count#8251L]
+- SortMergeJoin [day#8232], [day#8255], LeftOuter
:- *Sort [day#8232 ASC NULLS FIRST], false, 0
: +- Exchange hashpartitioning(day#8232, 200)
: +- InMemoryTableScan [day#8232, i#8233]
: +- InMemoryRelation [day#8232, i#8233], true, 10000, StorageLevel(disk, memory, deserialized, 1 replicas)
: +- *FileScan parquet mytable[day#8232,i#8233] Batched: true, Format: Parquet, Location: InMemoryFileIndex[hdfs://tablelocation], PartitionFilters: [], PushedFilters: [], ReadSchema: struct<day:int,i:int>
+- *Sort [day#8255 ASC NULLS FIRST], false, 0
+- *HashAggregate(keys=[day#8255], functions=[count(1)])
+- Exchange hashpartitioning(day#8255, 200)
+- *HashAggregate(keys=[day#8255], functions=[partial_count(1)])
+- InMemoryTableScan [day#8255]
+- InMemoryRelation [day#8255, i#8256], true, 10000, StorageLevel(disk, memory, deserialized, 1 replicas)
+- *FileScan parquet mytable[day#8232,i#8233] Batched: true, Format: Parquet, Location: InMemoryFileIndex[hdfs://tablelocation], PartitionFilters: [], PushedFilters: [], ReadSchema: struct<day:int,i:int>
为什么不缓存表?我正在使用Spark 2.1.1
答案 0 :(得分:0)
在缓存后尝试使用count(),以便触发一个动作,并在“计算”第二个计划之前完成缓存。
据我所知,第一个动作将触发缓存,但是由于Spark计划不是动态的,因此如果您在缓存后的第一个动作使用了该表两次,则必须将其读取两次(因为它不会缓存)表,直到它执行该操作为止。
如果上述方法不起作用[和/或您遇到了提到的错误],则可能与计划有关,您还可以尝试将DF转换为RDD,然后再转换为RDD(这样,计划将100%准确)。