• spark的UDF操作,RDD与DataFrame转换,RDD DataFrame DataSet的分析


    1 >spark的UDF操作

    理解:就是在sql中查询语句中提供了max(),avg(),min(),count()等函数操作, 同样的在spark中也有这些函数,但是用户的需求是多变的,比如:

    select name,age,length(name)/name.length from user

    很明显,不管是使用length(name)或是name.length都不可能实现这种效果,  于是spark提供UDF的操作可以实现这样的效果

    代码如下:

     val conf = new SparkConf().setMaster("local").setAppName("json")
     val spark = SparkSession.builder().config(conf).getOrCreate()
    
     def fun1(): Unit ={
       //得到conf
       val people:DataFrame = spark.read.json("E:\user.json")
       //通过SQL语句操作dataFrame
       people.createTempView("user")
    
       import spark.sql
       spark.udf.register[Int,String]("len",lengthName) //注册在spark中
       sql("select name,len(name) from user").show() 
    
     }
      //该方法需要注册在spark里
     def lengthName(name:String): Int ={
        name.length
     }

    执行:

    2 >RDD与DataFrame 相互转化

      >通过样例类转化: 

      /**
        * rdd与dataframe互操作
        *   1.通过样例类进行转换
        *   2.通过编程的方式进行转换
        */
      //1.通过样例类进行转化
      case class People(name:String, age:Int)  //样例类
      def fun2(): Unit ={
        val sc = spark.sparkContext
        val rdd  = sc.parallelize(Array("张三 12","成吉思汗 20","李四 33","占城 45"))
        val rddT = rdd.map(x=>{
          val p = x.split(" ")
          People(p(0),p(1).trim.toInt)
        })
        import spark.implicits._    //隐式转化
        val dataFrame:DataFrame = rddT.toDF  //将RDD转化dataFrame
        dataFrame.show()
        println(rdd.collect().toBuffer)
        println(dataFrame.rdd.collect().toBuffer)  //将dataFrame转化为RDD
        println(dataFrame.javaRDD.collect())     //同下,输出结果一样,
        println(dataFrame.toJavaRDD.collect())
      }

     通过查看源码: toJavaRDD与javaRDD都一样

    输出结果:

    dataFrame.show() 的输出
    +----+---+
    |name|age|
    +----+---+
    |  张三| 12|
    |成吉思汗| 20|
    |  李四| 33|
    |  占城| 45|
    +----+---+
    println(rdd.collect().toBuffer)
    ArrayBuffer(张三 12, 成吉思汗 20, 李四 33, 占城 45)
    println(dataFrame.rdd.collect().toBuffer) 的输出
    ArrayBuffer([张三,12], [成吉思汗,20], [李四,33], [占城,45])
    println(dataFrame.javaRDD.collect())     //同下,输出结果一样,
    println(dataFrame.toJavaRDD.collect())
    [[张三,12], [成吉思汗,20], [李四,33], [占城,45]]

    3 >RDD DataFrame DataSet数据集的理解

        参考:https://www.cnblogs.com/starwater/p/6841807.html

    相同点:

    1>全都是spark平台下的分布式弹性数据集,为处理超大型数据提供便利
    分布式弹性数据集:(spark的核心)弹性就是对于丢失的数据集,可以很快的重建
    参考:https://www.cnblogs.com/han-guang-xue/p/10036225.html
    
    2>三者都有惰性机制,在进行创建、转换,如map方法时,不会立即执行,只有在遇到Action如foreach时,三者才会开始遍历运算,
    极端情况下,如果代码里面有创建、转换,但是后面没有在Action中使用对应的结果,在执行时会被直接跳过,如
    val rdd=spark.sparkContext.parallelize(Seq(("a", 1), ("b", 1), ("a", 1)))
    rdd.map{line=>
      println("运行")    //不会执行
      line._1
    }
        
    3>三者都会根据spark的内存情况自动缓存运算,这样即使数据量很大,也不用担心会内存溢出
    
    区别:
    1> RDD一般和spark mlib同时使用  MLlib是Apache Spark的可扩展机器学习库。
    2> RDD不包含源数据的信息  RDD是分布式的Java对象的集合  
     如,RDD[Person]是以Person为类型参数,但是,Person类的内部结构对于RDD而言却是不可知的,DataFrame是一种以RDD为基础的分布式数据集,也就是分布式的Row对象的集合(每个Row对象代表一行记录),提供了详细的结构信息,
      也就是我们经常说的模式(schema),Spark SQL可以清楚地知道该数据集中包含哪些列、每列的名称和类型。
     
    3>
    这里主要对比Dataset和DataFrame,因为Dataset和DataFrame拥有完全相同的成员函数,区别只是每一行的数据类型不同DataFrame也可以叫Dataset[Row],每一行的类型是Row,
    不解析,每一行究竟有哪些字段,各个字段又是什么类型都无从得知,只能用上面提到的getAS方法或者共性中的第七条提到的模式匹配拿出特定字段而Dataset中,每一行是什么类型是不一定的,
    在自定义了case class之后可以很自由的获得每一行的信息

    可以看出,Dataset在需要访问列中的某个字段时是非常方便的,然而,如果要写一些适配性很强的函数时,如果使用Dataset,行的类型又不确定,可能是各种case class,无法实现适配,这时候用DataFrame即Dataset[Row]就能比较好的解决问题
     

     

  • 相关阅读:
    go context
    go etcd
    go logs
    go config
    go tail
    kafka与zookeeper
    go kafka
    go mysql
    array_map array_walk
    单独配置的nginx mysql 重启
  • 原文地址:https://www.cnblogs.com/han-guang-xue/p/10045413.html
Copyright © 2020-2023  润新知