Scala 在Spark中,如何读取用bucketBy编写的拼花文件,并保存拼花数据?
在ApacheSpark2.4.5中,如何打开使用bucketBy和saveAsTable编写的一组拼花文件 例如: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
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)