Scala 在Spark中,如何读取用bucketBy编写的拼花文件,并保存拼花数据?

Scala 在Spark中,如何读取用bucketBy编写的拼花文件,并保存拼花数据?,scala,apache-spark,parquet,Scala,Apache Spark,Parquet,在ApacheSpark2.4.5中,如何打开使用bucketBy和saveAsTable编写的一组拼花文件 例如: case class VeryVeryDeeplyNestedThing( s: String, nested1: OtherVeryDeeplyNestedThing ) case class OtherVeryDeeplyNestedThing ( youGetTheIdeaNoOneWantsToHandWriteASqlStatementForThese: N

在ApacheSpark2.4.5中,如何打开使用bucketBy和saveAsTable编写的一组拼花文件

例如:

case class VeryVeryDeeplyNestedThing(
  s: String,
  nested1: OtherVeryDeeplyNestedThing
)
case class OtherVeryDeeplyNestedThing (
  youGetTheIdeaNoOneWantsToHandWriteASqlStatementForThese: NestedMcNesty
)
List(VeryVeryDeeplyNestedThing(...)).toDS()
  .write
  .bucketBy(512, "s")
  .option("path", "/tmp/output")
  .format("parquet")
  .saveAsTable("mytable")
现在在
/tmp/output
中有一组拼花文件。将/tmp/output中的文件移动到/tmp/newPlace,并启动一个全新的spark会话

spark.read.parquet("/tmp/newPlace")
  .whatGoesHere?
你需要做些什么才能将它们读回,并使用它们所用的相同的拼凑信息?似乎信息并没有被烘焙到拼花地板文件中,或者是发生了什么

[编辑:添加了部分来自per@thebluephantom的工作示例,我认为这表明阅读确实需要一些特殊的东西]

如果像这样创建拼花地板文件:

scala> def base = spark.range(1, 160000, 1, 16).select($"id" as "key", rand(12) as "value")
base: org.apache.spark.sql.DataFrame

scala> import org.apache.spark.sql.SaveMode
import org.apache.spark.sql.SaveMode

scala> base.write.format("parquet").bucketBy(16, "key").sortBy("value").option("path", "/tmp/example").mode(SaveMode.Overwrite).saveAsTable("bucketed")

scala> base.write.format("parquet").option("path", "/tmp/exampleunbucketed").mode(SaveMode.Overwrite).saveAsTable("unbucketed")

scala> val t2 = spark.table("bucketed")
t2: org.apache.spark.sql.DataFrame = [key: bigint, value: double]

scala> val t3 = spark.table("bucketed")
t3: org.apache.spark.sql.DataFrame = [key: bigint, value: double]

// This is joining two bucketed tables

scala> t3.join(t2, Seq("key")).explain()
== Physical Plan ==
*(2) Project [key#51L, value#52, value#58]
+- *(2) BroadcastHashJoin [key#51L], [key#57L], Inner, BuildRight
   :- *(2) Project [key#51L, value#52]
   :  +- *(2) Filter isnotnull(key#51L)
   :     +- *(2) FileScan parquet default.bucketed[key#51L,value#52] Batched: true, Format: Parquet, Location: InMemoryFileIndex[hdfs://ip-172-31-66-61.ec2.internal:50070/tmp/example], PartitionFilters: [], PushedFilters: [IsNotNull(key)], ReadSchema: struct<key:bigint,value:double>, SelectedBucketsCount: 16 out of 16
   +- BroadcastExchange HashedRelationBroadcastMode(List(input[0, bigint, true]))
      +- *(1) Project [key#57L, value#58]
         +- *(1) Filter isnotnull(key#57L)
            +- *(1) FileScan parquet default.bucketed[key#57L,value#58] Batched: true, Format: Parquet, Location: InMemoryFileIndex[hdfs://ip-172-31-66-61.ec2.internal:50070/tmp/example], PartitionFilters: [], PushedFilters: [IsNotNull(key)], ReadSchema: struct<key:bigint,value:double>, SelectedBucketsCount: 16 out of 16
t4没有任何迹象表明它有扣


这有关系吗?它还带扣子吗?我是否误读了解释输出?或者我必须做些什么来确保t4使用bucket?

当我们在写入数据时使用bucketing或clustering时,它会将数据分割并保存为多个文件。 例如:

因此,当我们从新位置读取文件时,我们将能够读取整个数据

Bucketing有助于判断下推某些条件,因为它将限制spark仅读取特定文件


希望答案是肯定的。

你不知道。bucketBy是一个基于表的API,很简单

使用bucket by以便随后对表进行排序,并通过避免洗牌使后续的
联接更快。因此,通常将ETL用于临时、中间结果处理

读取不需要向查询中添加任何特殊内容,但联接的表必须都是带扣的,并且具有相同数量的bucket和分区。请看这篇优秀的帖子:。此外,spark sql shuffle分区的存储桶数必须相等

更新

如果数据较小,则可能会发生广播哈希连接,因此设置以下内容:

spark.conf.set("spark.sql.sources.bucketing.enabled", true)
spark.conf.set("spark.sql.autoBroadcastJoinThreshold", -1)

另外,我建议使用
spark.table
而不是
spark.read.parquet…
bucketBy ony使用table api。看

我确实看到了那篇帖子,但这也是我问这个问题的原因之一。他们在阅读的时候肯定在做一些特别的事情;他们从不只是从拼花文件开始。我将为我的问题添加更多信息。尽管没有什么。使用bucket by对表进行排序并加快后续联接。它进行排序,并与连接情况相关。catalyst optimizer看到了这一点,不需要洗牌。正如您在文档中看到的,没有什么特别的事情要做。bucketing的整个想法只是为了准备数据,以便进行无无序查询。先生,这个问题对我来说很清楚。我会照顾丁丁的。我在问题上补充了更多的信息。我问的是如何使用bucketing,而不是为什么。更新的答案。一切都按照我的预期进行。干杯
id,name,city
1,a,CA
2,b,NYC
3,c,NYC
4,d,CA

#So after bucketing based on city two file will be created 
id,name,city
1,a,CA
4,d,CA

and
id,name,city
2,b,NYC
3,c,NYC
spark.conf.set("spark.sql.sources.bucketing.enabled", true)
spark.conf.set("spark.sql.autoBroadcastJoinThreshold", -1)