鍵值對操作 上(Spark自學五)

右介發表於2017-10-24

鍵值對RDD是Spark中許多操作所需要的常見資料型別。

“分割槽”是用來讓我們控制鍵值對RDD在各節點上分佈情況的高階特性。使用可控的分割槽方式把常在一起被訪問的資料放在同一個節點上,可以大大減少應用的通訊開銷,帶來明顯的效能提升。

4.1 動機

  Spark為pair RDD提供了並行操作各個鍵或跨節點重新進行資料分組的操作介面。

4.2 建立Pair RDD

  當需要把一個普通的RDD轉為pair RDD時,可以呼叫map()函式來實現。下例為如何將由文字行組成的RDD轉換為以每行的第一個單詞為鍵的pair RDD。

  例4-1: 在Python中使用第一個單詞作為鍵建立出一個pair RDD

pairs = lines.map(lambda x: (x.split(" ")[0], x))

  例4-2: 在Scala中使用第一個單詞作為鍵建立出一個pair RDD

val pairs = lines.map(x => (x.split(" ")(0), x))

  4.3 Pair RDD的轉化操作

    Pair RDD可以使用所有標準RDD上的可用的轉化操作。

    Pair RDD的轉化操作(以鍵值對集合{(1,2),(3,4),(3,6)})為例:

      rdd.reduceByKey((x, y)=>x+y) 結果:{(1,2), (3,10)}

      rdd.groupByKey()                    結果:{(1,[2]),(3,[4,6])}

      rdd.mapValues(x => x+1)        結果:{(1,3),(3,5),(3,7)}

      rdd.keys()                                結果:{1,3,3}

      rdd.values()                             結果:{2,4,6}

      rdd.sortByKey()                       結果:{(1,2),(3,4),(3,6)}

    篩選掉長度超過20個字元的行,如下:

    例4-4: 用Python對第二個元素進行篩選

result = pairs.filter(lambda keyValue: len(keyValue[1]<20))

    例4-5: 用Scala對第二個元素進行篩選、

pairs.filter{case (key, value) => value.length < 20}

      4.3.1 聚合操作

      使用reduceByKey()和mapValues()來計算每個鍵的對應值的均值。

      例4-7:在Python中使用reduceByKey()和mapValues()計算每個鍵對應的平均值

rdd.mapValues(lambda x:(x, 1)).reduceByKey(lambda x, y: (x[0]+y[0], x[1]+y[1]))

      例4-8:在Python中使用reduceByKey()和mapValues()計算每個鍵對應的平均值

rdd.mapValues(x => (x, 1)).reduceByKey((x, y) => (x._1 + y._1, x._2 + y._2))

      解決分散式單詞計數問題如下

      例4-9: 用Python實現單詞計數

rdd = sc.textFile("s3://...")
words = rdd.flatMap(lambda x: x.split(" "))
result = words.map(lambda x: (x, 1)).reduceByKey(lambda x, y:x+y)

      例4-10: 用Scala實現單詞計數

val input = sc.textFile("s3://...")
val words = input.flatMap(x => x.split(" "))
val result = words.map(x => (x, 1)).reduceByKey((x, y) => x+y)

      我們可以使用countByValue()函式,以更快地實現單詞計數:input.flatMap(x => x.split(" ")).countByValue().

      Spark怎樣確定如何分割工作:每個RDD都有固定數目的分割槽,分割槽數決定了在RDD上執行操作時的並行度。

      例4-15: 在Python中自定義reduceByKey()的並行度

data = [("a", 3), ("b", 4), ("a", 1)]
sc.parallelize(data).reduceByKey(lambda x, y: x+y, 10)

    4.3.2 資料分組

       略

    4.3.3 連線

      連線資料操作:將有鍵的資料與另一組有鍵的資料一起使用。連線方式:右外連線、左外連線、交叉連線以及內連線。

      例4-17:在Scala shell中進行內連線

storeAddress = {
    (Store("Ritual"), "AAA"), (Store("Philz"), "BBB"), 
    (Store("Philz"), "CCC"), (Store("Starbucks"), "DDD")}

storeRating = {
    (Store("Ritual"), 4.9), (Store("Philz"), 4.8)}

storeAddress.rightOuterJoin(storeRating) == {
    (Store("Ritual"), "AAA", 4.9)),
    (Store("Philz"), "BBB", 4.8)),
    (Store("Philz"), "CCC", 4.8))}

      例4-18:leftOuterJoin()與rightOuterJoin()

storeAddress = {
    (Store("Ritual"), "AAA"), (Store("Philz"), "BBB"), 
    (Store("Philz"), "CCC"), (Store("Starbucks"), "DDD")}

storeRating = {
    (Store("Ritual"), 4.9), (Store("Philz"), 4.8)}

storeAddress.rightOuterJoin(storeRating) == {
    (Store("Ritual"), (Some("AAA"), 4.9)),
    (Store("Philz"), (Some("BBB"), 4.8)),
    (Store("Philz"), (Some("CCC"), 4.8))}

storeAddress.leftOuterJoin(storeRating) == {
    (Store("Ritual"), ("AAA", Some(4.9))),
    (Store("Starbucks"),("DDD",None)),     
    (Store("Philz"), ("BBB", Some(4.8))),
    (Store("Philz"), ("CCC", Some(4.8)))}

     4.3.4 資料排序

      略

      

相關文章