我有以下情况:
case class A(name:String,age:Int)
val df = List(A("s",2)).toDF
df.write.parquet("filePath")
val result = spark.read.parquet("filePath").as[A].select("age")
以上是否经过优化只能选择age
?看到result.explain
我看到以下
'Project [unresolvedalias('age, None)]
+- Relation[name#48,age#49] parquet
== Analyzed Logical Plan ==
age: int
Project [age#49]
+- Relation[name#48,age#49] parquet
== Optimized Logical Plan ==
Project [age#49]
+- Relation[name#48,age#49] parquet
== Physical Plan ==
*(1) FileScan parquet [age#49] Batched: true, Format: Parquet, Location: InMemoryFileIndex[file:/Volumes/Unix/workplace/Reconciliation/src/TFSReconciliationCore/~/Downloa..., PartitionFilters: [], PushedFilters: [], ReadSchema: struct<age:int>
似乎只有age
阅读。但是,目的是as
什么呢?我看身体计划正确吗?
是的,您正在阅读正确。实木复合地板文件有两列-name
和age
:
Relation[name#48,age#49] parquet
但实际上,只有这样age
才能被读取:
Project [age#49]
但是,这样做有什么目的呢?
与上面的优化一样,Spark需要创建一个内部架构。
在某些情况下,例如parquet
文件,我们有一个页脚,其中包含带有模式的元数据,尽管默认情况下,Spark必须读取所有页脚以合并可能的不同模式。
在其他(csv
,json
等)中,如果用户不提供架构,Spark需要扫描数据并创建它。
我们还需要一些通用容器,该容器将使我们能够访问这些值,并且有一个名为的容器Row
。
Row 是具有行的有序集合的通用行对象,可以通过序数/索引(也就是按序的通用访问),名称(即本机原始访问)或使用Scala的模式匹配来访问这些字段。
在您的示例中,编写以下代码完全可以:
spark.read.parquet("filePath").select("age")
read方法返回Dataframe
,实际上只是一个Dataset of Rows
。
当我们使用时,as
我们将转换Dataset[Row]
为几乎所有案例类都在Dataset[A]
哪里A
。
在我看来,它使代码更整洁,更易读。在使用类似SQL的方法时,它并没有太大区别,但是当我们需要将map / flatMap或自定义聚合添加到组合中时,代码将变得更加易于理解。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句