试图了解Hive分区与Spark分区的关系,最后提出有关连接的问题。
我有2个外部Hive表;由S3存储桶支持并由date
分区;所以在每个桶中都有名称格式为date=<yyyy-MM-dd>/<filename>
的密钥。
问题1:
如果我将这些数据读入Spark:
val table1 = spark.table("table1").as[Table1Row]
val table2 = spark.table("table2").as[Table2Row]
那么生成的数据集分别有多少个分区?分区等于S3中的对象数量?
问题2 :
假设两种行类型具有以下模式:
Table1Row(date: Date, id: String, ...)
Table2Row(date: Date, id: String, ...)
我希望在字段table1
和table2
上加入date
和id
:
table1.joinWith(table2,
table1("date") === table2("date") &&
table1("id") === table2("id")
)
Spark是否能够利用其中一个字段是Hive表中的分区键来优化连接的事实?如果是这样的话?
问题3 :
现在假设我使用的是RDD
:
val rdd1 = table1.rdd
val rdd2 = table2.rdd
AFAIK,使用RDD
API的联接语法如下所示:
rdd1.map(row1 => ((row1.date, row1.id), row1))
.join(rdd2.map(row2 => ((row2.date, row2.id), row2))))
同样,Spark是否能够利用Hive表中的分区键在连接中使用的事实?
答案 0 :(得分:3)
那么生成的数据集分别有多少个分区?分区等于S3中的对象数量?
无法回答您提供的信息。分区数in latest versions主要取决于spark.sql.files.maxPartitionByte
,但其他因素也可以发挥一定作用。
Spark是否能够利用其中一个字段是Hive表中的分区键以优化连接这一事实?
不是今天(Spark 2.3.0),但Spark可以利用bucketing(DISTRIBUTE BY
)来优化连接。见How to define partitioning of DataFrame?。一旦Data Source API v2稳定,这可能会在未来发生变化。
现在假设我正在使用RDD(...)同样,Spark是否能够利用Hive表中的分区键在连接中使用的事实?
完全没有。即使数据是分段的RDD转换,functional Dataset
transformations也是黑盒子。无法应用优化并在此处应用。
答案 1 :(得分:0)
总的来说,
Spark分区-大型分布式数据集的(逻辑)块。 Spark为单个分区生成一个Task,它将在执行程序JVM中运行。
Hive分区是一种通过将表基于分区键(列)划分为不同部分来将表组织为分区的方法。分区使访问数据更加简单明了。
很少可以调整的配置-
spark.sql.files.maxPartitionBytes
-读取文件时要打包到单个分区中的最大字节数(默认为128MB)
spark.sql.files.openCostInBytes
-可以同时扫描打开文件的估计成本(以字节数衡量)。将多个文件放入分区时使用。最好高估一下,然后,具有较小文件的分区将比具有较大文件的分区(首先安排)更快。 (默认4 MB)
spark.sql.shuffle.partitions
-配置在对连接或聚合进行数据混排时要使用的分区数。 (默认为200)