当我在窗口中使用partitionBy时,为什么我会使用spark / scala获得不同的结果?

时间:2017-06-13 08:14:29

标签: apache-spark apache-spark-sql

我使用Window.sum函数来获取RDD中值的总和,但是当我将DataFrame转换为RDD时,我发现结果只有一个分区。何时进行重新分区?

 val rdd = sc.parallelize(List(1,3,2,4,5,6,7,8), 4)
    val df = rdd.toDF("values").
        withColumn("csum", sum(col("values")).over(Window.orderBy("values")))
    df.show()
    println(s"numPartitions ${df.rdd.getNumPartitions}")
    // 1
    //df is:
//    +------+----+
//    |values|csum|
//    +------+----+
//    |     1|   1|
//    |     2|   3|
//    |     3|   6|
//    |     4|  10|
//    |     5|  15|
//    |     6|  21|
//    |     7|  28|
//    |     8|  36|
//    +------+----+

我在Window中添加了partitionBy,但结果是错误,我该怎么办?这是我的更改代码:

     val rdd=sc.parallelize(List(1,3,2,4,5,6,7,8),4)
        val sqlContext = new SQLContext(m_sparkCtx)
        import sqlContext.implicits._
        val df = rdd.toDF("values").withColumn("csum", sum(col("values")).over(Window.partitionBy("values").orderBy("values")))
        df.show()
        println(s"numPartitions ${df.rdd.getNumPartitions}")
       //1
//df is:
//    +------+----+
//    |values|csum|
//    +------+----+
//    |     1|   1|
//    |     6|   6|
//    |     3|   3|
//    |     5|   5|
//    |     4|   4|
//    |     8|   8|
//    |     7|   7|
//    |     2|   2|
//    +------+----+

2 个答案:

答案 0 :(得分:0)

Window函数有partitionBy api,用于对dataframeorderBy进行分组,以按升序或降序对分组行进行排序。

在您的第一个案例中,您尚未定义partitionBy,因此所有值都被归为一个dataframe以便进行排序,从而将数据混合到一个分区中。

但在第二种情况下,您partitionBy本身已定义values。因此,由于每个值都是不同的,因此每行被分组为单独的组。

第二种情况下的分区是200,因为当您没有定义分区并且发生随机播放时,这是spark中定义的默认分区

要获得第二种情况与第一种情况相同的结果,您需要将dataframe分组为第一种情况,即分组到一组。为此,您需要创建另一个具有常量值的column并将该值用于partitionBy

答案 1 :(得分:0)

将列创建为
withColumn("csum", sum(col("values")).over(Window.orderBy("values")))

Window.orderBy("values")正在排序列"值"的值在单个分区中,因为您还没有定义partitionBy()方法来定义分区。

这会将partition的数量从最初的4改为1.

在第二种情况下,分区为200,因为partitionBy()方法使用200作为默认分区。如果您需要分区数为4,则可以使用repartition(4)coalesce(4)

等方法

希望你明白这一点!