Spark窗口功能前N项性能问题

时间:2017-04-14 18:03:25

标签: apache-spark spark-dataframe

我正在尝试获取数据集中的前n项。

最初我这样做了。

var  df  = Seq( (1 , "row1") , (2,"row2"), (1,"row11")  , (1 , null) ).toDF()

df=df.select($"_1".alias("p_int"), $"_2".alias("p_string"))

val resultDf =df.where($"p_string".isNotNull).select( $"p_int" ,$"p_int" +1  , upper($"p_string") , rank().over(Window.partitionBy($"p_int").orderBy( $"p_string" )) as  "RANKINDEX", row_number().over(Window.partitionBy($"p_int").orderBy( $"p_string" )) as "ROWNUMBER" ).where($"ROWNUMBER" <=  2 )

但我想避免操作的性能成本“where($”ROWNUMBER“&lt; = 10)”

所以我决定做以下

var  df  = Seq( (1 , "row1") , (2,"row2"), (1,"row11")  , (1 , null) ).toDF()

df=df.select($"_1".alias("p_int"), $"_2".alias("p_string"))

val test =df.where($"p_string".isNotNull).select( $"p_int" ,$"p_int" +1  , upper($"p_string") , rank().over(Window.partitionBy($"p_int").orderBy( $"p_string" )) as  "RANKINDEX", row_number().over(Window.partitionBy($"p_int").orderBy( $"p_string" )) as "ROWNUMBER" )

implicit val encoder = RowEncoder(test.schema)

var  temp =test.mapPartitions( _.take(2))

但是,我的测试似乎表明这不会产生正确的输出。

任何想法为什么。从窗口数据集获取的迭代器上的take函数不会获得迭代器中的前n个元素吗?

1 个答案:

答案 0 :(得分:0)

Dataset的分区与PARTITION BY子句一一对应。 OVER (PARTITION BY ...)中的所有魔法都发生在更低的级别上,单个物理分区将处理多个ID。

你也不能真正挽救这项工作。要正确生成row_numbers,Spark必须对所有数据进行随机排序,排序和扫描。您需要更低级别的机制来避免完全混乱和排序(例如Aggregator使用二进制堆)。