我正在寻找一种检查点DataFrames的方法。 Checkpoint目前是RDD上的一个操作,但我找不到如何使用DataFrames。持久化和缓存(它们是彼此的同义词)可用于DataFrame,但它们不会“打破血统”,因此不适用于可循环数百(或数千)次迭代的方法。
例如,假设我有一个其签名为DataFrame =>的函数列表。数据帧。即使myfunctions有数百或数千个条目,我想有办法计算以下内容:
def foo(dataset: DataFrame, g: DataFrame => Unit) =
myfunctions.foldLeft(dataset) {
case (df, f) =>
val nextDF = f(df)
g(nextDF)
nextDF
}
答案 0 :(得分:20)
TL; DR:对于高达1.6的Spark版本,要实际获得"检查点DF",我建议的解决方案基于另一个答案,但有一个额外的行:
df.rdd.checkpoint
df.rdd.count
val df2 = sqlContext.createDataFrame(df.rdd, df.schema)
// df2 is checkpointed
<强>解释强>
经过进一步研究后更新。
正如所指出的,直接检查DataFrame当前不是(Spark 1.6.1),尽管Spark的Jira上有issue。
因此,可能的解决方法是在另一个答案中提出的建议:
df.rdd.checkpoint // Assuming the checkpoint dir has already been set
df.count // An action to compute the checkpoint
但是,使用此方法,只会检查df.rdd对象。这可以通过致电toDebugString
至df.rdd
来验证:
scala> df.rdd.toDebugString
(32) MapPartitionsRDD[1] at rdd at <console>:38 []
| ReliableCheckpointRDD[2] at count at <console>:38 []
然后在快速转换为toDebugString
之后调用df
(请注意我从JDBC源创建了我的DataFrame),返回以下内容:
scala> df.withColumn("new_column", lit(0)).rdd.toDebugString
res4: String =
(32) MapPartitionsRDD[5] at rdd at <console>:38 []
| MapPartitionsRDD[4] at rdd at <console>:38 []
| JDBCRDD[3] at rdd at <console>:38 []
df.explain
也会显示提示:
scala> df.explain
== Physical Plan ==
Scan JDBCRelation (...)
所以,要真正实现&#34;检查点&#34; DataFrame,我只能想到从检查点RDD创建一个新的:
val newDF = sqlContext.createDataFrame(df.rdd, df.schema)
// or
val newDF = df.rdd.map {
case Row(val1: Int, ..., valN: Int) => (val1, ..., valN)
}.toDF("col1", ..., "colN")
然后我们可以验证新的DataFrame是否为&#34;检查点&#34;:
1)newDF.explain
:
scala> newDF.explain
== Physical Plan ==
Scan PhysicalRDD[col1#5, col2#6, col3#7]
2)newDF.rdd.toDebugString
:
scala> newDF.rdd.toDebugString
res7: String =
(32) MapPartitionsRDD[10] at rdd at <console>:40 []
| MapPartitionsRDD[8] at createDataFrame at <console>:37 []
| MapPartitionsRDD[1] at rdd at <console>:38 []
| ReliableCheckpointRDD[2] at count at <console>:38 []
3)转型:
scala> newDF.withColumn("new_column", lit(0)).rdd.toDebugString
res9: String =
(32) MapPartitionsRDD[12] at rdd at <console>:40 []
| MapPartitionsRDD[11] at rdd at <console>:40 []
| MapPartitionsRDD[8] at createDataFrame at <console>:37 []
| MapPartitionsRDD[1] at rdd at <console>:38 []
| ReliableCheckpointRDD[2] at count at <console>:38 []
另外,我尝试了一些更复杂的转换,实际上,我能够检查newDF
对象是否已经过检查点。
因此,我发现可靠地检查DataFrame的唯一方法是通过检查点关联的RDD并从中创建一个新的DataFrame对象。
我希望它有所帮助。欢呼声。
答案 1 :(得分:7)
从spark 2.1开始,数据帧有一个可以直接使用的检查点方法(参见http://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.sql.Dataset),无需通过RDD。
答案 2 :(得分:4)
我想现在你必须要做
sc.setCheckpointDir("/DIR")
df.rdd.checkpoint
然后您必须对基础df.rdd
执行操作。致电df.ACTION
目前无效,仅df.rdd.ACTION
答案 3 :(得分:3)
延伸到Assaf Mendelson回答,
截至今日Spark版本2.2,DataSet#checkpoint()
API 进化和实验
在检查点之前必须使用SparkContext
提及CheckpointDir#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Delaunay_triangulation_2<K> Triangulation;
typedef Triangulation::Edge_iterator Edge_iterator;
typedef Triangulation::Point Point;
int main( )
{
std::ifstream in("data/voronoi.cin");
std::istream_iterator<Point> begin(in);
std::istream_iterator<Point> end;
Triangulation T;
T.insert(begin, end);
int ns = 0;
int nr = 0;
Edge_iterator eit =T.edges_begin();
for ( ; eit !=T.edges_end(); ++eit) {
CGAL::Object o = T.dual(eit);
if (CGAL::object_cast<K::Segment_2>(&o)) {++ns;}
else if (CGAL::object_cast<K::Ray_2>(&o)) {++nr;}
}
std::cout << "The Voronoi diagram has " << ns << " finite edges "
<< " and " << nr << " rays" << std::endl;
return 0;
}
到目前为止,implementation for DataSet checkpoint是将DataSet转换为RDD然后检查它。
spark.sparkContext.setCheckpointDir("checkpoint/dir/location")
val ds: Dataset[Long] = spark.range(10).repartition('id % 2)
// do checkpoint now, it will preserve partition also
val cp: Dataset[Long] = ds.checkpoint()
答案 4 :(得分:1)
最初的问题是关于Scala Spark的,但是我认为添加PySpark语法也很有用,这非常相似。请注意,与cache
/ persist
不同的是,checkpoint
不能就地运行(最初使我绊倒了):
spark.sparkContext.setCheckpointDir("/foo/bar")
df = df.checkpoint()