【问题标题】:Is a select after casting a data frame to dataset optimized?将数据框转换为数据集后的选择是否已优化?
【发布时间】:2019-12-11 21:13:21
【问题描述】:

我有以下场景:

 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 的作用是什么?我在阅读物理计划时是否正确?

【问题讨论】:

    标签: dataframe apache-spark apache-spark-sql parquet catalyst-optimizer


    【解决方案1】:

    是的,你没看错。 Parquet 文件有两列 - nameage

     Relation[name#48,age#49] parquet
    

    但实际上只有age会被读取:

     Project [age#49]
    

    那么 as 有什么作用呢?

    对于优化,就像上面的优化一样,Spark 需要创建一个内部架构。

    在某些情况下,例如parquet 文件,我们有一个包含带有架构的元数据的页脚,但默认情况下,Spark 必须读取所有页脚以合并可能不同的架构。
    在其他情况下(csvjson 等),如果用户不提供模式,Spark 需要扫描数据并创建它。

    我们还需要一些通用容器,它可以让我们访问这些值,我们有一个叫做Row

    Row 是具有有序字段集合的通用行对象 可以通过序数/索引访问(又名通用访问 ordinal),一个名称(又名原生原始访问)或使用 Scala 的 模式匹配。

    在您的示例中,编写以下代码非常好:

    spark.read.parquet("filePath").select("age")
    

    Read 方法返回Dataframe,实际上只是一个Dataset of Rows
    当我们使用as 时,我们将Dataset[Row] 转换为Dataset[A],其中A 几乎可以是任何case-class。

    在我看来,它使代码更简洁、更易读。在使用类似 SQL 的方法时并没有太大区别,但是当我们需要将 map/flatMap 或自定义聚合添加到混合中时,代码会变得更容易理解。

    【讨论】:

      猜你喜欢
      • 2013-04-02
      • 1970-01-01
      • 2022-06-15
      • 2022-12-12
      • 2021-01-22
      • 2017-10-24
      • 1970-01-01
      • 1970-01-01
      • 2015-11-28
      相关资源
      最近更新 更多