从spark 2.0.1开始我有一些问题。我阅读了很多文档,但到目前为止找不到足够的答案:
df.select("foo")
df.select($"foo")
myDataSet.map(foo.someVal)
是类型安全的,不会转换为RDD
但保留在DataSet表示中/没有额外的开销(2.0.0的性能明智)df.select("foo")
类型安全?
答案 0 :(得分:28)
df.select("foo")
和df.select($"foo")
之间的区别是签名。前一个至少需要一个String
,后者需要零个或多个Columns
。除此之外没有实际的区别。 myDataSet.map(foo.someVal)
类型检查,但由于任何Dataset
操作使用RDD
个对象,并与DataFrame
操作进行比较,因此会产生很大的开销。我们来看一个简单的例子:
case class FooBar(foo: Int, bar: String)
val ds = Seq(FooBar(1, "x")).toDS
ds.map(_.foo).explain
== Physical Plan ==
*SerializeFromObject [input[0, int, true] AS value#123]
+- *MapElements <function1>, obj#122: int
+- *DeserializeToObject newInstance(class $line67.$read$$iw$$iw$FooBar), obj#121: $line67.$read$$iw$$iw$FooBar
+- LocalTableScan [foo#117, bar#118]
正如您所见,此执行计划需要访问所有字段,并且必须DeserializeToObject
。
没有。通常,其他方法不是语法糖并生成明显不同的执行计划。例如:
ds.select($"foo").explain
== Physical Plan ==
LocalTableScan [foo#117]
与之前显示的计划相比,它可以直接访问列。它不是API的限制,而是操作语义差异的结果。
如果没有map语句,我怎么能df.select(“foo”)类型安全?
没有这样的选择。虽然键入的列允许您将Dataset
静态转换为另一个静态类型Dataset
:
ds.select($"bar".as[Int])
没有类型安全。还有其他尝试包括类型安全优化操作,like typed aggregations,但这个实验性API。
为什么我应该使用UDF / UADF而不是地图
这完全取决于你。 Spark中的每个分布式数据结构都有自己的优点和缺点(例如参见Spark UDAF with ArrayType as bufferSchema performance issues)。
就个人而言,我发现静态类型Dataset
是最不实用的:
不要提供与Dataset[Row]
相同的优化范围(尽管它们共享存储格式和一些执行计划优化,但它不能完全受益于代码生成或堆外存储),也不能访问DataFrame
的所有分析能力。
类型化转换是黑盒子,有效地为优化器创建分析障碍。例如,不能通过类型转换推送选择(过滤器):
ds.groupBy("foo").agg(sum($"bar") as "bar").as[FooBar].filter(x => true).where($"foo" === 1).explain
== Physical Plan ==
*Filter (foo#133 = 1)
+- *Filter <function1>.apply
+- *HashAggregate(keys=[foo#133], functions=[sum(cast(bar#134 as double))])
+- Exchange hashpartitioning(foo#133, 200)
+- *HashAggregate(keys=[foo#133], functions=[partial_sum(cast(bar#134 as double))])
+- LocalTableScan [foo#133, bar#134]
与:相比:
ds.groupBy("foo").agg(sum($"bar") as "bar").as[FooBar].where($"foo" === 1).explain
== Physical Plan ==
*HashAggregate(keys=[foo#133], functions=[sum(cast(bar#134 as double))])
+- Exchange hashpartitioning(foo#133, 200)
+- *HashAggregate(keys=[foo#133], functions=[partial_sum(cast(bar#134 as double))])
+- *Filter (foo#133 = 1)
+- LocalTableScan [foo#133, bar#134]
这会影响谓词下推或投影下推等功能。
没有RDDs
那么灵活,本机只支持一小部分类型。
Encoders
方法转换Dataset
时,as
的“类型安全”存在争议。由于数据形状不使用签名进行编码,因此编译器只能验证是否存在Encoder
。相关问题:
答案 1 :(得分:2)
Spark Dataset
比Spark Dataframe
更强大。小例子 - 您只能创建Dataframe
Row
,Tuple
或任何原始数据类型,但Dataset
可让您创建任何非基本类型的Dataset
太。即你可以从字面上创建对象类型的Dataset
。
前:
case class Employee(id:Int,name:String)
Dataset[Employee] // is valid
Dataframe[Employee] // is invalid
答案 2 :(得分:-1)
DATAFRAME:DataFrame是允许对数据进行架构视图的抽象。
案例类Person(名称:字符串,年龄:整数,地址:字符串)
定义的类Person
scala> val df =列表(人(“ Sumanth”,23,“ BNG”)
DATASET:数据集是对Dataframe API的扩展,API是最新的抽象,试图同时提供RDD和Dataframe的优点。