SparkSQL

1.SparkSql简介

  • Spark SQL是Spark处理数据的一个模块
  • 专门用来处理结构化数据的模块,像json,parquet,avro,csv,普通表格数据等均可。
  • 与基础RDD的API不同,SparkSQL中提供的接口将提供给更多关于结构化数据和计算的信息,并针对这些信息,进行额外的处理优化。

2.SparkSql操作方式

  1. SparkSql shell 类似于hive shell
  2. DataFrames API
    与RDD相似,增加了数据结构描述信息部分
  3. DataSets API
    集成了RDD强类型和DataFrames结构化的优点

3.DataFrames相关操作

综合示例-1.6.x

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.SQLContext
object SparkSqlTest {
  def main(args: Array[String]) {
   val conf = new SparkConf()
   conf.setMaster("local");
   conf.setAppName("TestSparkSql");
   val sc = new SparkContext(conf)
   val sqlContext = new SQLContext(sc)
   // 添加将RDD转化为DataFrame的功能包引入
   import sqlContext.implicits._
   val df = sqlContext.read.json("file:\\E:\\test\\job003\\sparksql\\input_weibo.json")
   //默认显示内容的top20
   df.show()
   // 打印内容对应的表结构
   df.printSchema()
   // 选择内容当中的某一个列对应的内容
   df.select("content").show()
   // 选择任意列并进行自定义操作
   df.select(df("content"), df("commentCount"), df("commentCount") + 10000).show()
   // 选择评论数大于100的数据显示出来
   df.filter(df("commentCount") > 100).show()
  
   // 按userId进行分组计数统计
   df.groupBy("userId").count().show()
  
   //分组统计结果按默认升序排列
   df.groupBy("userId").count().orderBy("count").show()
  
   //分组统计结果按降序排列
   import org.apache.spark.sql.functions._
   df.groupBy("userId").count().orderBy(desc("count")).show()
   sc.stop();
  }
}

综合示例-2.3.x

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.SQLContext
import org.apache.spark.sql.SparkSession

object TestSparkSqlFor2_3_x {
  def main(args: Array[String]): Unit = {
    //1、构建spark session
    val sparkSession = SparkSession
      .builder()
      .appName("SparkSql-2.3.2-TestCase")
      .master("local[*]")
      .getOrCreate()

    // For implicit conversions like converting RDDs to DataFrames
    import sparkSession.implicits._

    //2、构建data frames
    val df = sparkSession.read.json("F:\\test_sbt\\FirstSpark4Scala\\input_json.txt")

    //3、df算子操作    
    // 打印内容对应的表结构
    df.printSchema()
    // 选择内容当中的某一个列对应的内容
    df.select("content").show()
    // 选择任意列并进行自定义操作
    df.select(df("content"), df("commentCount"), df("commentCount") + 10000).show()
    // 选择评论数大于100的数据显示出来
    df.filter(df("commentCount") > 100).show()

    // 按userId进行分组计数统计
    df.groupBy("userId").count().show()

    //分组统计结果按默认升序排列
    df.groupBy("userId").count().orderBy("count").show()

    //分组统计结果按降序排列
    import org.apache.spark.sql.functions._
    df.groupBy("userId").count().orderBy(desc("count")).show()

    //4、停掉相关会话
    sparkSession.stop()

  }
}

4.RDD转化为DataFrame

将无结构化数据转化成有结构化数据(两种方式)

  • 反射推断
  • 程序编码实现数据与结构的对应,达到转化目标

2.3代码实现

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.SQLContext
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.types.StructType
import org.apache.spark.sql.types.StructField
import org.apache.spark.sql.types.StringType
import org.apache.spark.sql.Row

object TestRddToDataFrameFor2_3_x {
  def main(args: Array[String]): Unit = {
    //1、构建spark session
    val sparkSession = SparkSession
      .builder()
      .appName("SparkSql-2.3.2-TestCase")
      .master("local[*]")
      .getOrCreate()

    // For implicit conversions like converting RDDs to DataFrames
    import sparkSession.implicits._

    //2、构建scheme
    val schema =
      StructType(
        "stdNo name classNo className".split(" ").map(fieldName => StructField(fieldName, StringType, true)))

    //3、构建rdd,linesRDD
    val studentRDD = sparkSession.sparkContext.textFile("F:\\test_sbt\\FirstSpark4Scala\\student_mysql.txt")

    //4、将linesRDD转换成Row rdd
    val rowRDD = studentRDD.map(_.split("\\t")).map(p => Row(p(0), p(1), p(2), p(3)))

    //5、创建df,由row rdd + scheme
    val studentDataFrame = sparkSession.createDataFrame(rowRDD, schema)

    //6、df算子操作
    studentDataFrame.printSchema()
    studentDataFrame.show()

    //7、停掉相关会话
    sparkSession.stop()
  }
}

5.DataFrame数据持久化

• 综合示例实现-2.3.x(与1.6.x差距核心在sparkSession抽象)

import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.sql.SQLContext
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.types.StructType
import org.apache.spark.sql.types.StructField
import org.apache.spark.sql.types.StringType
import org.apache.spark.sql.Row

object TestSparksqlPersistFor2_3_x {
  def main(args: Array[String]): Unit = {
      //1、构建spark session
    val sparksql = SparkSession
      .builder()
      .appName("SparkSql-2.3.2-TestCase")
      .master("local[*]")
      .getOrCreate()

    // For implicit conversions like converting RDDs to DataFrames
    import sparksql.implicits._

    //2、构建scheme
     val df = sparksql.read.json("F:\\test_sbt\\FirstSpark4Scala\\input_json.txt")

    //3、注册成表
    df.createTempView("weibo")
	
    //4、df算子操作
    var resultDF = sparksql.sql("select * from weibo")
    resultDF.repartition(1).write.format("parquet").save("F:\\test_sbt\\FirstSpark4Scala\\save3")

    //5、停掉相关会话
    sparksql.stop()

  }
}

6.DataSets的Spark2.3.2版本上的应用

package com.tl.job019.sparksql

import org.apache.spark.sql.SparkSession
//样例类
case class Student(name: String, age: Long, address: String)
/**
 * 抽象数据类型DataSet测试类
 */
object TestSparkSqlDataSet {
  def main(args: Array[String]): Unit = {
    //1、构建spark session
    val sparkSession = SparkSession
      .builder()
      .appName("SparkSql-2.3.2-TestCase")
      .master("local[*]")
      .getOrCreate()
    //引入自动隐式类型转换
    import sparkSession.implicits._

    // 从基础数据对象类型创建DataSet
    val primitiveDS = Seq(1, 2, 3).toDS()
    val col = primitiveDS.map(_ + 1).collect() // Returns: Array(2, 3, 4)
    col.foreach(println)
    println("-----------------")
    primitiveDS.show()

    // 已为样例类case class创建完成编码类Encoder
    val caseClassDS = Seq(Student("脱口秀大会", 3, "北京")).toDS()
    caseClassDS.show()
    
    // 指定相应的文件导入形成样例类对应的DataSet,通过json的key和样例类的字段名称对应即可
    val path = "F:\\test_sbt\\FirstSpark4Scala\\student_data.txt"
    val peopleDS = sparkSession.read.json(path).as[Student]
    peopleDS.select("name", "age", "address").show()

    //关停会话上下文
    sparkSession.stop()
  }
}

7.多数据集抽象类型对比分析

spark抽象数据集列表

  • RDD
  • DataFrame
  • DataSet

相同点:

  • 全都是spark平台下的分布式弹性数据集,为处理超大型数据提供便利
  • 三者都有惰性机制,在进行Transform操作时不会立即执行,在遇到Action操作时会正式提交作业执行。
  • 均采用spark的内存运算和优化策略,内存使用和执行效率上均可以得到保障。
  • 均有partition的概念,便于分布式并行计算处理,达到分而治之。 均有许多共同的函数,如map、filter、sort等。
  • 在进行三者的相关操作时候,个别特殊操作时必须引入一个相同的包依赖。( 早期称为 import sqlContext.implicits.,最新版本称为import spark.implicits.)
  • DF和DS均可以通过模式匹配获取内部的变量类型和值。
  • DF和DS产生于SparkSql,天然支持SparkSql。

• 区别点
RDD

  • 不支持SparkSql操作,均需进行转成DF或是DS才行。
  • 类型是安全的,编译时候即可检查出类型错误。(强类型)
  • 机器间通信、IO操作均需要序列化、反序列化对象,性能开销大。

DataFrame

  • 有scheme的RDD:比RDD增加了数据的描述信息。
  • 比RDD的API更丰富,增加了针对结构化数据API。
  • 只有一个固定类型的DataSet,即为DataFrame=DataSet[Row]
  • 序列化和反序列化时做了结构化优化,减少了不必要的结构化信息的序列化,提高了执行效率

DataSet

  • 强类型的DataFrame,与DF有完全相同的成员函数。
  • 每行的类型不固定,需要使用模式匹配case class后,获取实际的类信息、字段类型、字段值。
  • 访问对象数据时,比DF更加直接简单。
  • 在序列化和反序列化时,引入了Encoder机制,达到按需序列化和反序列化,不必像之前整个对象操作了,进一步提高了效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值