读取文件后直接查询文件与查询数据帧

时间:2018-09-27 16:09:30

标签: scala apache-spark apache-spark-sql parquet

方法1: 直接查询木地板文件为:

val sqlDF = spark.sql("SELECT columns FROM parquet.`sample.parquet`")

方法2: 读取实木复合地板文件后查询数据框:

df = spark.read.parquet(path_to_parquet_file)
df.select(columns)

方法3: 查询临时视图的方式为:

df.createOrReplaceTempView("sample")
val sqlDF = spark.sql("SELECT columns FROM sample")
  1. 在幕后,这3个对象基本上都以相同的方式执行吗?
  2. 在方法1中,实木复合地板是否被转换为数据框/数据集 在执行查询之前?
  3. 这3种方法中哪一种有效?为什么? (如果它们是 不同)
  4. 这些方法是否有特定的用例? (如果它们是 不同)

谢谢!

2 个答案:

答案 0 :(得分:1)

简短回答

是的。您所说明的使用Spark查询Parquet文件的3种方式都是以相同的方式执行的。

长期回答

之所以如此,是Spark的两个功能的组合:lazy evaluationquery optimization

作为开发人员,您可以将Spark操作分为多个步骤(如方法2中所述)。在内部,Spark(懒惰地)联合评估操作并对其进行优化。在这种情况下,Spark可以通过修剪列来优化操作(基本上,它不会将整个镶木地板数据读入内存;只读取您请求的特定列。)

创建临时视图的第三种方法就是命名已读取的数据,以便您可以在以后的操作中进行引用。首先,它不会改变其计算方式。

有关Spark在阅读Parquet中执行的优化的更多信息,请参阅此in-depth article

注意: 正如我在对该问题的评论中提到的那样,您已在方法2中选择了特定的列;而另外两个读取全部数据。由于这些操作本质上是不同的,因此执行上会有所不同。上面的答案假定在这三种方法中的每一种中都执行了类似的操作(从文件中读取完整数据或某些特定列)。

答案 1 :(得分:1)

如果您尝试评估哪个“ 3”最适合相同的目标,则两者之间没有区别。 physical plan告诉您一个问题-“在幕后吗?”。

方法1:

sqlDF = spark.sql("SELECT CallNumber,CallFinalDisposition FROM parquet.`/tmp/ParquetA`").show()

== Physical Plan ==
CollectLimit 21
+- *(1) Project [cast(CallNumber#2988 as string) AS CallNumber#3026, CallFinalDisposition#2992]
   +- *(1) FileScan parquet [CallNumber#2988,CallFinalDisposition#2992] Batched: true, Format: Parquet, Location: InMemoryFileIndex[dbfs:/tmp/ParquetA], PartitionFilters: [], PushedFilters: [], ReadSchema: struct<CallNumber:int,CallFinalDisposition:string>

方法2:

df = spark.read.parquet('/tmp/ParquetA')
df.select("CallNumber","CallFinalDisposition").show()

== Physical Plan ==
CollectLimit 21
+- *(1) Project [cast(CallNumber#3100 as string) AS CallNumber#3172, CallFinalDisposition#3104]
   +- *(1) FileScan parquet [CallNumber#3100,CallFinalDisposition#3104] Batched: true, Format: Parquet, Location: InMemoryFileIndex[dbfs:/tmp/ParquetA], PartitionFilters: [], PushedFilters: [], ReadSchema: struct<CallNumber:int,CallFinalDisposition:string>

方法3:

tempDF = spark.read.parquet('/tmp/ParquetA/')
tempDF.createOrReplaceTempView("temptable");
tiny = spark.sql("SELECT CallNumber,CallFinalDisposition FROM temptable").show()

== Physical Plan ==
CollectLimit 21
+- *(1) Project [cast(CallNumber#2910 as string) AS CallNumber#2982, CallFinalDisposition#2914]
   +- *(1) FileScan parquet [CallNumber#2910,CallFinalDisposition#2914] Batched: true, Format: Parquet, Location: InMemoryFileIndex[dbfs:/tmp/ParquetA], PartitionFilters: [], PushedFilters: [], ReadSchema: struct<CallNumber:int,CallFinalDisposition:string>