读书笔记-Spark快速大数据分析

第三章 RDD编程

P35

fold函数的一个小问题记录一下

scala> val linesa = sc.parallelize(List(1,2,3,4))
linesa: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[20] at parallelize at <console>:26

scala> linesa.fold(10)(_*_)
res29: Int = -1769803776

scala> linesa.collect().fold(10)(_*_)
res30: Int = 240

P35 aggregate函数

这个函数不限制返回结果的格式
函数累加器前面那坨的参数类型和合并函数的参数类型应该和提供的初始值(下面例子中是 (Int, Int))一样
累加器后面那坨的参数类型应该和input中的一样

object test {
  def main(args: Array[String]): Unit = {
    val input = List(1,2,3,4)
    val result = input.aggregate((0, 0))(
      // 通过一个函数把RDD中的元素合并起来放入累加器.
      // 累加器 (元组累加元组结果,RDD单个元素值)=>(元组累加结果+RDD单个元素,元组累加计数+1)
      (acc, value) => {println(acc,value); (acc._1 + value, acc._2 + 1)},  
      // 考虑到每个节点是在本地进行累加的,最终,还需要提供第二个函数来将累加器两两合并.
      // 下面这里println不会执行,只是一个累加器
      (acc1, acc2) => {println(acc1,acc2) ; (acc1._1 + acc2._1, acc1._2 + acc2._2)})  
    print(result)
//    输出
//    ((0,0),1)
//    ((1,1),2)
//    ((3,2),3)
//    ((6,3),4)
//    (10,4)
  }
}

P36

take(n)返回RDD中的n个元素,并且尝试只访问尽量少的分区,因此该操作会得到一个不均衡的集合.需要注意的是,这些操作返回元素的顺序与你预期的可能不一样.这些操作对于单元测试和快速调试都很有用,但是在处理大规模数据时会遇到瓶颈.
如果为数据定义了顺序,就可以使用top()从RDD中获取前几个元素.top()会使用数据的默认顺序,但我们也可以提供自己的比较函数,来提取前几个元素.

P37

takeOrdered(num)(ordering) 从RDD中按照提供的顺序返回最前面的num个元素
ordering这里好像有一些隐式声明的知识点

第四章 键值对操作

P44

这里是大括号
pairs.filter{case (key, value) => value.length < 20}

P50

如果你发现自己写出了先使用groupByKey()然后再对值使用reduce()或者fold()的代码,你很有可能可以通过使用一种根据键进行聚合的函数来更高效地实现同样的效果。对每个键归约数据,返回对应每个键的归约值的RDD,而不是把RDD归约为一个内存中的值。例如,rdd. reduceByKey( func)与rdd. groupByKey( ).mapValues(value => value. reduce(func))等价,但是前者更为高效,因为它避免了为每个键创建存放值的列表的步骤。

P54

//在Scala中以字符串顺序对整数进行自定义排序  这里的隐式声明? 
val input: RDD[(Int, Venue)] = ...
implicit val sortIntegersByString = new Ordering[Int] {
  override def compare(a: Int, b: Int) = a.toString.compare(b.toString)
}
rdd.sortByKey()

P55

在 Scala 和 Java 中,你可以使用 RDD 的 partitioner 属性(Java 中使用 partitioner() 方法)来获取 RDD 的分区方式。 3 它会返回一个scala.Option 对象,这是 Scala 中用来存放可能存在的对象的容器类。你可以对这个 Option 对象调用 isDefined() 来检查其中是否有值,调用 get() 来获取其中的值

P59

为了最大化分区相关优化的潜在作用,你应该在无需改变元素的键时尽量使用 mapValues() 或 flatMapValues()



一些问题

scala> a.collect
res14: Array[Int] = Array(1, 2)

scala> c.collect
res15: Array[Int] = Array(1, 2, 3, 4, 5, 6)

scala> c.filter(x=>(a.filter(_ == x).count > 0))
// 上面这行会报错
// org.apache.spark.SparkException: RDD transformations and actions can only be invoked by the driver, not inside of other transformations; for example, rdd1.map(x => rdd2.values.count() * x) is invalid because the values transformation and count action cannot be performed inside of the rdd1.map transformation. For more information, see SPARK-5063.
//rdd的嵌套可以执行,但是无法实现,内部的rdd无法执行行为操作。根据SPARK-5063,RDD的嵌套操作是不被允许的。
// 如 https://stackoverflow.com/questions/48078416/suddenly-throwing-this-rdd-lacks-a-sparkcontext-it-was-working-before-every-code




// user_lever是 RDD[(String, String)]
user_level.mapPartitions((t: Iterator[(String, Int)]) => {
      t.map((imei_tag: (String, Int)) =>{
        val imei: String = imei_tag._1
        val tag: String = imei_tag._2.toString
        println(imei)
        println(tag)
      })
    })
这部分没有输出, 需要理清
map:遍历RDD,将函数f应用于每一个元素,返回新的RDD(transformation算子)。
foreach:遍历RDD,将函数f应用于每一个元素,无返回值(action算子)。
mapPartitions:遍历操作RDD中的每一个分区,返回新的RDD(transformation算子)。
foreachPartition:遍历操作RDD中的每一个分区。无返回值(action算子)
https://blog.csdn.net/qq_17310871/article/details/103434808

user_histogram_1.filter(res6.contains(_._1)) // 错
user_histogram_1.filter(x=>res6.contains(x._1)) // 对

posted @ 2021-10-16 14:13  种树人  阅读(73)  评论(0编辑  收藏  举报