【Spark學習】Partitioner分區器初體驗

Partitioner源碼

abstract class Partitioner extends Serializable {
  def numPartitions: Int
  def getPartition(key: Any): Int
}

源碼解釋:
一個對象,定義如何按鍵對鍵值對RDD中的元素進行分區。
將每個鍵映射到一個分區ID,從0到“numPartitions-1”。
注意,partitioner必須是確定性的,即它必須返回給定的相同分區id
相同的分區鍵。

簡單來說:
getPartition方法根據輸入的k-v對的key值返回一個Int型數據。可以理解爲這個Int數據就是分區的編號。

1.下面是Partitioner自定義分區器的例子
需求
根據日期的年份對數據分區,分區繼承Partitioner類並重寫三個方法,分區數設置爲4 ,2013、2014、2015、其它年份分別放在一個分區
對文件裏的取時間data和第二個字段組成新rdd,進行分區後進行保存
數據格式(分隔符爲 “,” )
數據文件下載地址
在這裏插入圖片描述
代碼演示

import org.apache.spark.rdd.RDD
import org.apache.spark.{Partitioner, SparkConf, SparkContext}

object test04 {
  def main(args: Array[String]): Unit = {
    //構建sc對象
    val conf = new SparkConf().setMaster("local[*]").setAppName("test04")
    val sc = new SparkContext(conf)

    //讀取外部文件
    val data: RDD[String] = sc.textFile("D:\\ChromeCoreDownloads\\000002.csv")

    //分割每行數據,取出每行前兩個字段並做爲鍵值對
    val tuple = data.map(line => {
      val fields = line.split(",")
      fields(0) -> fields(1)
    })

    //filter(! _._1.contains("date")) 過濾掉字段名
    //partitionBy(new CustomPartitioner(4)) 使用自定義分區器,分區數爲 4
    val result = tuple.filter(! _._1.contains("date")).partitionBy(new CustomPartitioner(4))

    //將輸出文件保存到 out 文件夾
    result.saveAsTextFile("out")

  }
}

//自定義分區器
//需要重寫 Partitioner 的兩個方法
class CustomPartitioner(numPartition:Int) extends Partitioner {
  override def numPartitions: Int = numPartition

  override def getPartition(key: Any): Int = {
    //key 這裏的類型爲Any
    //需要將它轉換爲String類型,以便於後面的取值
    val k = key.asInstanceOf[String]
    //對date數據進行模式匹配
    //k = 2013/10/21  k(3) = 3
    k(3) match {
      case '3' => 0 //將k(3)爲3的放在 0 號分區
      case '4' => 1 //將k(3)爲4的放在 1 號分區
      case '5' => 2 //將k(3)爲5的放在 2 號分區
      case _ => 3   //將k(3)爲其他的放在 3 號分區
    }
  }
}

運行結果
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章