SparkSQL的简单使用

SparkSQL

1、简介

DataFrame

  • 在 Spark 中,DataFrame 是一种以 RDD 为基础的分布式数据集,类似于传统数据库中的二维表格。DataFrame 与 RDD 的主要区别在于,前者带有 schema 元信息,即 DataFrame 所表示的二维表数据集的每一列都带有名称和类型。这使得 Spark SQL 得以洞察更多的结构 信息,从而对藏于 DataFrame 背后的数据源以及作用于 DataFrame 之上的变换进行了针对性的优化,最终达到大幅提升运行时效率的目标。反观 RDD,由于无从得知所存数据元素的具体内部结构,Spark Core 只能在 stage 层面进行简单、通用的流水线优化。
  • 同时,与 Hive 类似,DataFrame 也支持嵌套数据类型(struct、array 和 map)。从 API 易用性的角度上看,DataFrame API 提供的是一套高层的关系操作,比函数式的 RDD API 要 更加友好,门槛更低。



DataSet

  • DataSet 是分布式数据集合。DataSet 是 Spark 1.6 中添加的一个新抽象,是 DataFrame 的一个扩展。它提供了 RDD 的优势(强类型,使用强大的 lambda 函数的能力)以及 Spark SQL 优化执行引擎的优点。DataSet 也可以使用功能性的转换(操作 map,flatMap,filter 等等)。
    • DataSet 是 DataFrame API 的一个扩展,是 SparkSQL 最新的数据抽象
    • 用户友好的 API 风格,既具有类型安全检查也具有 DataFrame 的查询优化特性;
    • 用样例类来对 DataSet 中定义数据的结构信息,样例类中每个属性的名称直接映射到 DataSet 中的字段名称;
    • DataSet 是强类型的。比如可以有 DataSet[Car],DataSet[Person]。
    • DataFrame 是 DataSet 的特列,DataFrame=DataSet[Row] ,所以可以通过 as 方法将 DataFrame 转换为DataSet。Row 是一个类型,跟 Car、Person 这些的类型一样,所有的表结构信息都用 Row 来表示。获取数据时需要指定顺序




2、Shell命令

DataFrame

  • 创建 DataFrame

    # 支持 csv format jdbc json load option options orc parquet schema table text textFile 多种创建
    spark.read.[csv format jdbc json load option options orc parquet schema table text textFile]
    
    # 事例(json的方式创建,json文件需要保证每行都是json格式)
    val df = spark.read.json("data/user.json")
    
  • SQL语法

    # 查询
    spark.sql("select查询语句")
    
    #事例
    # 1、创建 DataFrame
    val df = spark.read.json("data/user.json")
    # 2、创建临时表 user
    df.createOrReplaceTempView("user")
    # 3、查询
    spark.sql("SELECT * FROM user")
    
  • DSL语法(调用方法)

    #事例
    # 1、创建 DataFrame
    val df = spark.read.json("data/user.json")
    # 2、查看"username"列数据
    df.select("name").show()
    # 2、查看"username"列数据以及"age+1"数据
    # 注意:涉及到运算的时候, 每列都必须使用$, 或者采用引号表达式:单引号+字段名
    df.select($"username",$"age" + 1).show
    df.select('username, 'age + 1).show()
    
  • RDD <-> DataFrame(相互转换)

    # RDD 转换为 DataFrame(.toDF)
    rdd.toDF(字段名)
    rdd.toDF("id", "name")
    
    # DataFrame 转换为 RDD(.rdd)
    df.rdd
    



DataSet

  • 创建DataSet

    # 1、创建类
    case class Person(name: String, age: Long)
    # 2、创建DataSet(.toDS)
    Seq(Person("fff", 20), Person("zzz", 30)).toDS()
    
  • RDD <-> DataSet(相互转换)

    case class User(name:String, age:Int)
    
    # RDD 转换为 DataSet(.toDS)
    rdd.map{data => User(data._1, data._2)}.toDS
    
    # DataSet 转换为 RDD(.rdd)
    ds.rdd
    
  • DataFrame <-> DataSet(相互转换)

    case class User(name:String, age:Int)
    
    # DataFrame  转换为 DataSet(.as[])
    df.as[User]
    
    # DataSet 转换为 DataFrame (.rdd)
    ds.toDF
    




3、IDEA开发

环境准备

  • 添加依赖(pom.xml)

    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-core_2.12</artifactId>
        <version>3.0.0</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-yarn_2.12</artifactId>
        <version>3.0.0</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-sql_2.12</artifactId>
        <version>3.0.0</version>
    </dependency>
    



RDD、DataFrame、DataSet 三者相互转换

import org.apache.spark.SparkConf
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession}

object Spark01_SQL_Basic {
  def main(args: Array[String]): Unit = {

    //TODO 创建SparkSession
    //创建Spark配置对象
    val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("sparkSQL")
    //创建SparkSession对象
    val spark: SparkSession = SparkSession.builder().config(sparkConf).getOrCreate()
    import spark.implicits._

    //TODO 业务逻辑
    //创建DataFrame(json)
    val df: DataFrame = spark.read.json("datas/user.json")

    //DataFrame => SQL语法
    df.createOrReplaceTempView("user")
    spark.sql("select * from user").show()

    //DataFrame => DSL语法
    df.select("name", "age").show()
    df.select($"age" + 1).show()
    df.select('age + 1).show()

    //创建DataSet
    val ds: Dataset[Int] = Seq(1, 2, 3, 4).toDS()
    ds.show()

    //RDD <=> DataFrame(相互转换)
    val rdd: RDD[(Int, String, Int)] = spark.sparkContext.makeRDD(List((1, "fff", 20)))
    val df1: DataFrame = rdd.toDF("id", "name", "age")
    val rdd1: RDD[Row] = df1.rdd

    //DataFrame <=> DataSet(相互转换)
    val ds2: Dataset[User] = df1.as[User]
    val df2: DataFrame = ds2.toDF()

    //RDD <=> DataSet(相互转换)
    val ds3: Dataset[User] = rdd.map(data => User(data._1, data._2, data._3)).toDS()
    val rdd3: RDD[User] = ds3.rdd

        
    //TODO 关闭连接
    spark.stop()
  }

  //创建User类
  case class User(id: Int, name: String, age: Int)

}



自定义函数

UDF

import org.apache.spark.SparkConf
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession}

object Spark02_SQL_UDF {
  def main(args: Array[String]): Unit = {

    //TODO 创建SparkSession
    val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("sparkSQL")
    val spark: SparkSession = SparkSession.builder().config(sparkConf).getOrCreate()
    import spark.implicits._

    //TODO 业务逻辑
    //DataFrame
    val df: DataFrame = spark.read.json("datas/user.json")

    df.createOrReplaceTempView("user")

    //自定义udf,第一个参数:名称,第二个参数:逻辑方法
    spark.udf.register("prifix", (name: String) => "Name: " + name)
    spark.sql("select prifix(name), age from user").show()


    //TODO 关闭连接
    spark.stop()
  }
}



UDAF

import org.apache.spark.SparkConf
import org.apache.spark.sql.expressions.Aggregator
import org.apache.spark.sql.{DataFrame, Encoder, Encoders, SparkSession, functions}

object Spark03_SQL_UDAF {
  def main(args: Array[String]): Unit = {

    //TODO 创建SparkSession
    val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("sparkSQL")
    val spark: SparkSession = SparkSession.builder().config(sparkConf).getOrCreate()

    //TODO 业务逻辑
    val df: DataFrame = spark.read.json("datas/user.json")

    df.createOrReplaceTempView("user")

    //自定义UDAF
    spark.udf.register("ageAvg", functions.udaf(new MyUDAF))
    spark.sql("select ageAvg(age) from user").show()


    //TODO 关闭连接
    spark.stop()
  }

  //创建Buff类
  case class Buff(var total: Long, var count: Long)

  //自定义UDAF类
  class MyUDAF extends Aggregator[Long, Buff, Long]{
    //buff初始数据
    override def zero: Buff = Buff(0L, 0L)

    //缓冲区中的业务逻辑
    override def reduce(b: Buff, a: Long): Buff = {
      b.total += a
      b.count += 1
      b
    }

    //将缓冲区间合并的业务逻辑
    override def merge(b1: Buff, b2: Buff): Buff = {
      b1.total += b2.total
      b1.count += b2.count
      b1
    }

    //最终业务逻辑
    override def finish(reduction: Buff): Long = reduction.total / reduction.count

    //buff编码类型(Encoders.product:自定义类型)
    override def bufferEncoder: Encoder[Buff] = Encoders.product

    //输出编码类型(Encoders.scalaLong:系统自带类型)
    override def outputEncoder: Encoder[Long] = Encoders.scalaLong
  }
}




4、加载和保存方式

加载数据

# 支持 csv format jdbc json load option options orc parquet schema table text textFile 多种加载方式
spark.read.[csv format jdbc json load option options orc parquet schema table text textFile]

# json
spark.read.json("data/user.json")

# load
#	format("…"):指定加载的数据类型,包括"csv"、"jdbc"、"json"、"orc"、"parquet"和"textFile"
#	option("…"):在"jdbc"格式下需要传入 JDBC 相应参数,url、user、password 和 dbtable
#	load("…"):在"csv"、"jdbc"、"json"、"orc"、"parquet"和"textFile"格式下需要传入加载数据的路径
spark.read.format("…")[.option("…")].load("…")
# load -> json
spark.read.format("json").load("data/user.json")
# load -> jdbc
spark.read.format("jdbc")
      .option("url", "jdbc:mysql://localhost:3306/test")
      .option("user", "root")
      .option("password", "123456")
      .option("dbtable", "test")
      .load()



保存数据

# 支持 csv jdbc json orc parquet textFile… … 保存数据方式
df.write.[csv jdbc json orc parquet textFile… …]

# 事例
df.write.save("路径")

# save
#	format("…"):指定保存的数据类型,包括"csv"、"jdbc"、"json"、"orc"、"parquet"和"textFile"
#	option("…"):在"jdbc"格式下需要传入 JDBC 相应参数,url、user、password 和 dbtable
#	mode("…"):数据保存类型,"error"(default,抛异常)、"append"(追加)、"overwrite"(覆盖)、"ignore"(忽略)
#	save ("…"):在"csv"、"orc"、"parquet"和"textFile"格式下需要传入保存数据的路径
df.write.format("…")[.option("…")][.mode("…")].save("…")
#save -> json
spark.write.format("json").save("data/user.json")
# save -> jdbc
df.write.format("jdbc")
      .option("url", "jdbc:mysql://localhost:3306/test")
      .option("user", "root")
      .option("password", "123456")
      .option("dbtable", "test1")
      .mode(SaveMode.Append)
      .save()



API

MySQL

import org.apache.spark.SparkConf
import org.apache.spark.sql.expressions.Aggregator
import org.apache.spark.sql._

object Spark04_SQL_JDBC {
  def main(args: Array[String]): Unit = {

    //TODO 创建SparkSession
    val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("sparkSQL")
    val spark: SparkSession = SparkSession.builder().config(sparkConf).getOrCreate()

        
    //TODO 业务逻辑
    val df: DataFrame = spark.read.format("jdbc")
      .option("url", "jdbc:mysql://localhost:3306/test")
      .option("user", "root")
      .option("password", "123456")
      .option("dbtable", "test")
      .load()
    df.show()

    df.write.format("jdbc")
      .option("url", "jdbc:mysql://localhost:3306/test")
      .option("user", "root")
      .option("password", "123456")
      .option("dbtable", "test1")
      .mode(SaveMode.Append)
      .save()


    //TODO 关闭连接
    spark.stop()
  }
}



Hive

  • 导入依赖(pom.xml)

    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-core_2.12</artifactId>
        <version>3.0.0</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-yarn_2.12</artifactId>
        <version>3.0.0</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-sql_2.12</artifactId>
        <version>3.0.0</version>
    </dependency>
    
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.27</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-hive_2.12</artifactId>
        <version>3.0.0</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.hive</groupId>
        <artifactId>hive-exec</artifactId>
        <version>1.2.1</version>
    </dependency>
    
  • 程序

    import org.apache.spark.SparkConf
    import org.apache.spark.sql._
    
    object Spark05_SQL_Hive {
      def main(args: Array[String]): Unit = {
    
        //TODO 创建SparkSession
        val sparkConf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("sparkSQL")
        //开启hive支持(enableHiveSupport)
        val spark: SparkSession = SparkSession.builder().enableHiveSupport().config(sparkConf).getOrCreate()
    
         
        //TODO 业务逻辑
        spark.sql("show tables").show()
    
    
        //TODO 关闭连接
        spark.stop()
      }
    }
    
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值