为什么在重新分配Spark Dataframe时会得到这么多空分区?

时间:2018-06-05 07:49:13

标签: apache-spark pyspark apache-spark-sql partitioning

我想对数据帧进行分区" df1"在3列。对于这3列,这个数据帧恰好有990个独特的组合:

In [17]: df1.createOrReplaceTempView("df1_view")

In [18]: spark.sql("select count(*) from (select distinct(col1,col2,col3) from df1_view) as t").show()
+--------+                                                                      
|count(1)|
+--------+
|     990|
+--------+

为了优化这个数据帧的处理,我想分区df1以获得990个分区,每个密钥可能一个:

In [19]: df1.rdd.getNumPartitions()
Out[19]: 24

In [20]: df2 = df1.repartition(990, "col1", "col2", "col3")

In [21]: df2.rdd.getNumPartitions()
Out[21]: 990

我写了一个简单的方法来计算每个分区中的行:

In [22]: def f(iterator):
    ...:     a = 0
    ...:     for partition in iterator:
    ...:         a = a + 1
    ...:     print(a)
    ...: 

In [23]: df2.foreachPartition(f)

我注意到我得到的实际上是628个具有一个或多个键值的分区,以及362个空分区。

我假设火花会以均匀的方式重新分配(1个键值= 1个分区),但这似乎不是这样,我觉得这种重新分区正在增加数据偏差,即使它应该是另一种方式...

Spark用于对列上的数据帧进行分区的算法是什么? 有没有办法实现我认为可能的目标?

我在Cloudera上使用Spark 2.2.0。

1 个答案:

答案 0 :(得分:3)

要跨分区分发数据,需要以某种方式将列的值转换为分区的索引。 Spark中有两个默认分区程序--HashPartitioner和RangePartitioner。 Spark中的不同转换可以应用不同的分区 - 例如<input type="email" id="email" class="form-control" (keyup)="checkValue($event)" formControlName="inputValue"> <button type="button" id="verifyBtn" [disabled]="personalDtlsForm.get('inputValue').invalid" class="btn btn-primary btn-large" (click)="verify()">Verify</button> this.personalDtlsForm = this.formBuilder.group({ inputValue: [null, [Validators.required, Validators.email]] }); 将应用散列分区程序。

基本上,将值转换为分区索引的散列分区程序公式为join。在您的情况下,多个值映射到相同的分区索引。

如果您想要更好的分发,可以实现自己的分区程序。有关它的更多信息,请here以及herehere