Spark:将RDD元素拆分为块

时间:2017-05-09 18:48:07

标签: scala apache-spark apache-spark-mllib chunks

我在Scala中编写了一个相对简单的Spark作业,它从S3读取一些数据,执行一些转换和聚合,最后将结果存储到存储库中。

在最后阶段,我有一个我的域模型的RDD,我想将它们分组成一大块元素,以便我可以在我的存储库中进行一些大量插入。

我使用RDDFunctions.sliding方法来实现这一点并且它的工作几乎没问题。这是我的代码的简化版本:

val processedElements: RDD[DomainModel] = _
RDDFunctions.fromRDD(processedElements)
    .sliding(500, 500)
    .foreach { elementsChunk =>
        Await.ready(repository.bulkInsert(elementsChunk), 1.minute)
    }

问题是,例如,如果我有1020个元素,那么只有1000个元素在我的存储库中结束。如果窗口大小大于剩余元素的数量,滑动看起来像忽略任何其他元素。

有什么方法可以解决这个问题吗?如果没有,是否有其他方法可以在不使用RDDFunctions.sliding的情况下实现相同的行为?

2 个答案:

答案 0 :(得分:0)

你能不能只使用// set up our data series with 50 random data points var seriesData = [ [], [], [] ]; var random = new Rickshaw.Fixtures.RandomData(150); var graph, slider, hoverDetail, legend, shelving, order, highlight; for (var i = 0; i < 150; i++) { random.addData(seriesData); } // instantiate our graph! graph = new Rickshaw.Graph({ element: document.getElementById("chart"), width: 960, height: 500, renderer: 'line', stroke: true, preserve: true, series: [{ color: "#c05020", data: seriesData[0], name: 'New York' }, { color: "#30c020", data: seriesData[1], name: 'London' }, { color: "#6060c0", data: seriesData[2], name: 'Tokyo' }] }); graph.render(); slider = new Rickshaw.Graph.RangeSlider({ graph: graph, element: $("#slider")[0] }); hoverDetail = new Rickshaw.Graph.HoverDetail({ graph: graph }); legend = new Rickshaw.Graph.Legend({ graph: graph, element: $("#legend")[0] }); shelving = new Rickshaw.Graph.Behavior.Series.Toggle({ graph: graph, legend: legend }); order = new Rickshaw.Graph.Behavior.Series.Order({ graph: graph, legend: legend }); highlight = new Rickshaw.Graph.Behavior.Series.Highlight({ graph: graph, legend: legend }); 和手动批量管理?

foreachPartition

答案 1 :(得分:0)

根据RDDFunctions doc,如果窗口大小超过剩余项目数,那么Spark的sliding(与Scala不同)会生成空的RDD。 Spark也不具有Scala grouped的等价性。

如果您知道要创建的群组数量,则可能适用的解决方法是使用modulo过滤器拆分RDD。以下是将RDD分为5组的简单例子:

val rdd = sc.parallelize(Seq(
  (0, "text0"), (1, "text1"), (2, "text2"), (3, "text2"), (4, "text2"), (5, "text5"),
  (6, "text6"), (7, "text7"), (8, "text8"), (9, "text9"), (10, "text10"), (11, "text11")
))

def g(n:Int)(x: Int): Boolean = { x % 5 == n }

val rddList = (0 to 4).map( n => rdd.filter(x => g(n)(x._1)) )

(0 to 4).foreach(n => rddList(n).collect.foreach(println))

(0,text0)
(5,text5)
(10,text10)

(1,text1)
(6,text6)
(11,text11)

(2,text2)
(7,text7)

(3,text2)
(8,text8)

(4,text2)
(9,text9)