我有一个具有一百万条记录的数据框。看起来像这样-
df.show()
+--------------------+--------------------++-------------
| feature1| feature2| domain |
+--------------------+--------------------++-------------
|[2.23668528E8, 1....|[2.23668528E8, 1....| domain1 |
|[2.23668528E8, 1....|[2.23668528E8, 1....| domain2 |
|[2.23668528E8, 1....|[2.23668528E8, 1....| domain1 |
|[2.23668528E8, 1....|[2.23668528E8, 1....| domain2 |
|[2.23668528E8, 1....|[2.23668528E8, 1....| domain1 |
理想的分区大小为128 MB,让我们假设domain列具有两个唯一值(domain1和domain2),考虑到这一点,我有两个问题-
如果我执行df.repartition("domain")
,并且一个分区不能容纳特定域密钥的所有数据,那么应用程序会失败还是会根据数据自动创建合适的分区? / p>
假设在上面的数据中已经基于域密钥进行了重新分区,因此将存在两个分区(唯一的密钥为domain1和domain2)。现在,假设domain1和domain2重复了1000000次,我将基于该域进行自联接。因此,对于每个域,我将获得大约10 ^ 12条记录。考虑到我们有两个分区,并且联接期间分区的数量没有变化,两个新分区是否能够处理1000000条记录?
答案 0 :(得分:2)
答案取决于您的数据大小。当一个分区不能保存属于一个分区值的所有数据(例如domain1
)时,将创建更多分区,最多spark.sql.shuffle.partitions
个分区。如果您的数据太大,即一个分区将超过2GB的限制(有关说明,另请参见Why does Spark RDD partition has 2GB limit for HDFS?),则重新分区将导致 OutOfMemoryError 。
正如提供完整答案的旁注所示:能够将数据放入一个分区不一定意味着一个分区值只生成一个分区。除其他因素外,这取决于执行程序的数量以及之前如何对数据进行分区。 Spark将尝试避免不必要的改组,因此可能会为一个分区值生成多个分区。
因此,要防止作业失败,您应该调整spark.sql.shuffle.partitions
或将所需数量的分区以及分区列一起传递到repartition
。