sparkSQL相关应用案例

目录

 

1、sparksql操作hivesql

2、sparksql操作jdbc数据源

3、sparksql保存数据操作

4、 sparksql中自定义函数

5、sparksql整合hive

6、sparksql处理点击流日志数据案例


1、sparksql操作hivesql

(1)pom文件添加相关maven依赖

添加依赖

        
            org.apache.spark
            spark-hive_2.11
            2.3.3
        

(2)代码

//todo:利用sparksql操作hivesql
object HiveSupport {
  def main(args: Array[String]): Unit = {
    //1、构建SparkSession对象
    val spark: SparkSession = SparkSession.builder()
      .appName("HiveSupport")
      .master("local[2]")
      .enableHiveSupport()    //开启对hive的支持
      .getOrCreate()
    //2、直接使用sparkSession去操作hivesql语句

      //2.1 创建一张hive表
       spark.sql("create table people(id string,name string,age int) row format delimited fields terminated by ','")
      //2.2 加载数据到hive表中
       spark.sql("load data local inpath './data/fengge.txt' into table people ")
      //2.3 查询
      spark.sql("select * from people").show()

    spark.stop()
  }
}

2、sparksql操作jdbc数据源

spark sql可以通过 JDBC 从关系型数据库中读取数据的方式创建DataFrame,通过对DataFrame一系列的计算后,还可以将数据再写回关系型数据库中。

(1)通过sparksql加载mysql表中的数据

//todo:利用sparksql加载mysql表中的数据
object DataFromMysql {
  def main(args: Array[String]): Unit = {
    //1、创建SparkConf对象
    val sparkConf: SparkConf = new SparkConf().setAppName("DataFromMysql").setMaster("local[2]")
    //2、创建SparkSession对象
    val spark: SparkSession = SparkSession.builder().config(sparkConf).getOrCreate()
    //3、读取mysql表的数据
        //3.1 指定mysql连接地址
        val url="jdbc:mysql://node03:3306/spark"
        //3.2 指定要加载的表名
        val tableName="user"
        // 3.3 配置连接数据库的相关属性
        val properties = new Properties()

      //用户名
      properties.setProperty("user","root")
      //密码
      properties.setProperty("password","123456")

     val mysqlDF: DataFrame = spark.read.jdbc(url,tableName,properties)

      //打印schema信息
      mysqlDF.printSchema()
      //展示数据
      mysqlDF.show()

    //把dataFrame注册成表
    mysqlDF.createTempView("user")

    spark.sql("select * from user where age >30").show()

    spark.stop()
  }

}

(2)通过sparksql保存结果数据到mysql表中

//todo:通过sparksql把结果数据写入到mysql表中
object Data2Mysql {
  def main(args: Array[String]): Unit = {
    //1、创建SparkSession
    val spark: SparkSession = SparkSession
                                .builder()
                                .appName("Data2Mysql")
                                .master("local[2]")     //集群运行模式时,不要指定master
                                .getOrCreate()
    //2、读取mysql表中数据
    //2.1 定义url连接
    val url="jdbc:mysql://node03:3306/spark"
    //2.2 定义表名
    val table="user"
    //2.3 定义属性
    val properties=new Properties()
    properties.setProperty("user","root")
    properties.setProperty("password","123456")

    val mysqlDF: DataFrame = spark.read.jdbc(url,table,properties)

    //把dataFrame注册成一张表
      mysqlDF.createTempView("user")

    //通过sparkSession调用sql方法
      val result: DataFrame = spark.sql("select * from user where age > 30")

    //保存结果数据到mysql表中
     //mode:指定数据的插入模式
        //overwrite: 表示覆盖,如果表不存在,事先帮我们创建
        //append   :表示追加, 如果表不存在,事先帮我们创建
        //ignore   :表示忽略,如果表事先存在,就不进行任何操作
        //error    :如果表事先存在就报错(默认选项)
    result.write.mode("append").jdbc(url,"fengge",properties)  //本地运行模式
    // result.write.mode(args(0)).jdbc(url,args(1),properties)   //集群运行模式

    //关闭
     spark.stop()
  }
}

查看数据库,发现数据库多了个fengge的表:

sparkSQL相关应用案例_第1张图片

集群运行任务提交脚本:

提交任务脚本

spark-submit \
--master spark://node01:7077 \
--class com.fengge.sparkSQL.Data2Mysql \
--executor-memory 1g \
--total-executor-cores 1 \
--driver-class-path /home/hadoop/mysql-connector-java-5.1.38.jar \   //指定一个Driver端所需要的额外jar
--jars /home/hadoop/mysql-connector-java-5.1.38.jar \   //指定executor端所需要的额外jar
spark_class03-1.0-SNAPSHOT.jar \
append  fengge

 

3、sparksql保存数据操作

//todo:sparksql可以把结果数据保存到不同的外部存储介质中
object SaveResult {

  def main(args: Array[String]): Unit = {
    //1、创建SparkConf对象
    val sparkConf: SparkConf = new SparkConf().setAppName("SaveResult").setMaster("local[2]")

    //2、创建SparkSession对象
    val spark: SparkSession = SparkSession.builder().config(sparkConf).getOrCreate()

    //3、加载数据源
    val jsonDF: DataFrame = spark.read.json("E:\\data\\score.json")

    //4、把DataFrame注册成表
    jsonDF.createTempView("t_score")

    //todo:5、统计分析
    val result: DataFrame = spark.sql("select * from t_score where score > 80")

    //保存结果数据到不同的外部存储介质中
    //todo: 5.1 保存结果数据到文本文件  ----  保存数据成文本文件目前只支持单个字段,不支持多个字段
    result.select("name").write.text("./data/result/123.txt")

    //todo: 5.2 保存结果数据到json文件
    result.write.json("./data/json")

    //todo: 5.3 保存结果数据到parquet文件
    result.write.parquet("./data/parquet")

    //todo: 5.4 save方法保存结果数据,默认的数据格式就是parquet
    result.write.save("./data/save")

    //todo: 5.5 保存结果数据到csv文件
    result.write.csv("./data/csv")

    //todo: 5.6 保存结果数据到表中
    result.write.saveAsTable("t1")

    //todo: 5.7  按照单个字段进行分区 分目录进行存储
    result.write.partitionBy("classNum").json("./data/partitions")

    //todo: 5.8  按照多个字段进行分区 分目录进行存储
    result.write.partitionBy("classNum","name").json("./data/numPartitions")

    spark.stop()
  }

}

4、 sparksql中自定义函数

//TODO:自定义sparksql的UDF函数    一对一的关系
object SparkSQLFunction {

  def main(args: Array[String]): Unit = {
    //1、创建SparkSession
    val sparkSession: SparkSession = SparkSession.builder().appName("SparkSQLFunction").master("local[2]").getOrCreate()

    //2、构建数据源生成DataFrame
    val dataFrame: DataFrame = sparkSession.read.text("E:\\data\\test_udf_data.txt")

    //3、注册成表
    dataFrame.createTempView("t_udf")

    //4、实现自定义的UDF函数
    //小写转大写(java代码)
    sparkSession.udf.register("low2Up",new UDF1[String,String]() {
      override def call(t1: String): String = {
        t1.toUpperCase
      }
    },StringType)

    //大写转小写
    sparkSession.udf.register("up2low",(x:String)=>x.toLowerCase)      //scala简写

//    sparkSession.udf.register("low2up",new UDF1[String,String]() {
//      override def call(t1: String): String = {
//        t1.toLowerCase
//      }
//    },StringType)


    //4、把数据文件中的单词统一转换成大小写
    sparkSession.sql("select  value from t_udf").show()
    sparkSession.sql("select  low2Up(value) from t_udf").show()
    sparkSession.sql("select  up2low(value) from t_udf").show()

    sparkSession.stop()
  }
}

sparkSQL相关应用案例_第2张图片

sparkSQL相关应用案例_第3张图片

sparkSQL相关应用案例_第4张图片

5、sparksql整合hive

 

1、需要把hive安装目录下的配置文件hive-site.xml拷贝到每一个spark安装目录下对应的conf文件夹中;

sparkSQL相关应用案例_第5张图片

sparkSQL相关应用案例_第6张图片

然后分发到其他节点上:scp hive-site.xml node02:$PWD

2、需要一个连接mysql驱动的jar包拷贝到每一个spark安装目录下对应的jars文件夹中;

sparkSQL相关应用案例_第7张图片

然后分发到其他节点上。

3、可以使用spark-sql脚本 后期执行sql相关的任务。

启动脚本

spark-sql \
--master spark://node01:7077 \
--executor-memory 1g \
--total-executor-cores 1 \
--conf spark.sql.warehouse.dir=hdfs://node01:8020/user/hive/warehouse   //指定数据库地址(hdfs)

在spark-sql中创建数据库:

sparkSQL相关应用案例_第8张图片

在hive中查看该数据库:

sparkSQL相关应用案例_第9张图片

sparkSQL相关应用案例_第10张图片

6、sparksql处理点击流日志数据案例

 

(1)校验日志数据进行字段解析提取的工具类

 class AccessLog(
                      ipAddress: String, // IP地址
                      clientId: String, // 客户端唯一标识符
                      userId: String, // 用户唯一标识符
                      serverTime: String, // 服务器时间
                      method: String, // 请求类型/方式
                      endpoint: String, // 请求的资源
                      protocol: String, // 请求的协议名称
                      responseCode: Int, // 请求返回值:比如:200、401
                      contentSize: Long, // 返回的结果数据大小
                      url:String, //访问的url地址
                      clientBrowser:String //客户端游览器信息
                    )
/**
  * 校验日志数据进行字段解析提取的工具类
  */
object AccessLogUtils {
  val regex: Regex =
    """^(\S+) (\S+) (\S+) \[([\w:/]+\s[+\-]\d{4})\] "(\S+) (\S+) (\S+)" (\d{3}) (\d+) (\S+) (.*)""".r

  /**
    * 验证一下输入的数据是否符合给定的日志正则,如果符合返回true;否则返回false
    *
    * @param line
    * @return
    */
  def isValidateLogLine(line: String): Boolean = {
    val options = regex.findFirstMatchIn(line)

    if (options.isEmpty) {
      false
    } else {
      true
    }
  }

  /**
    * 解析输入的日志数据
    *
    * @param line
    * @return
    */
  def parseLogLine(line: String): AccessLog = {

      // 从line中获取匹配的数据
      val options = regex.findFirstMatchIn(line)

      // 获取matcher
      val matcher = options.get

      // 构建返回值
      AccessLog(
        matcher.group(1), // 获取匹配字符串中第一个小括号中的值
        matcher.group(2),
        matcher.group(3),
        matcher.group(4),
        matcher.group(5),
        matcher.group(6),
        matcher.group(7),
        matcher.group(8).toInt,
        matcher.group(9).toLong,
        matcher.group(10),
        matcher.group(11)
      )
  }
}

(2)指标统计

  * 日志分析案例
  */
object LogAnalysis {

  //定义url连接
  val url="jdbc:mysql://node03:3306/spark"
  //定义属性
  val properties=new Properties()
  properties.setProperty("user","root")
  properties.setProperty("password","123456")

  def main(args: Array[String]): Unit = {
    //1、构建sparkConf对象
    val sparkConf: SparkConf = new SparkConf().setAppName("LogAnalysis").setMaster("local[2]")

    //2、构建sparkSession对象
      val spark: SparkSession = SparkSession.builder().config(sparkConf).getOrCreate()

    //3、获取sparkContext对象
      val sc: SparkContext = spark.sparkContext
       sc.setLogLevel("warn")

    //4、读取数据文件
       val logRDD: RDD[String] = sc.textFile("./logs/access.log")

    //5、过滤脏数据,然后解析
        val rightRDD: RDD[String] = logRDD.filter(line => AccessLogUtils.isValidateLogLine(line))
        val accessLogRDD: RDD[AccessLog] = rightRDD.map(line => AccessLogUtils.parseLogLine(line))

    //6、将RDD转换成DataFrame
     import spark.implicits._
     val accessLogDF: DataFrame = accessLogRDD.toDF

    //7、将DataFrame注册成一张表
    accessLogDF.createTempView("access")

    //todo:8、指标分析
      //todo:8.1 求contentSize的平均值,最大值以及最小值
         val result1 = spark.sql(
           """
             |select
             |date_sub(from_unixtime(unix_timestamp(),'yyyy-MM-dd'),1) as time,
             |AVG(contentSize) as avg_contentSize,
             |MAX(contentSize) as max_contentSize,
             |MIN(contentSize) as min_contentSize
             |from access
           """.stripMargin)

           //展示结果数据
          result1.show()
          //保存结果数据到mysql表中
          //result1.write.jdbc(url,"t_contentSizeInfo",properties)


      //todo:8.2 求 pv 和 uv
        val result2 = spark.sql(
          """
            |select
            |date_sub(from_unixtime(unix_timestamp(),'yyyy-MM-dd'),1) as time,
            |count(*) as pv,
            |count(distinct ipAddress) as uv
            |from access
          """.stripMargin)

          //展示结果数据
        result2.show()
         //保存结果数据到mysql表中
       // result2.write.jdbc(url,"t_uv_pv",properties)


     //todo:8.3 求各个响应码出现的次数
        val result3 = spark.sql(
          """
            |select
            |date_sub(from_unixtime(unix_timestamp(),'yyyy-MM-dd'),1) as time,
            |responseCode as code,
            |count(*) as count
            |from access
            |group by responseCode
          """.stripMargin)

         //展示结果数据
        result3.show()
         //保存结果数据到mysql表中
        //result3.write.jdbc(url,"t_responseCode",properties)

     //todo:8.4 求访问url次数最多的前N位
        val result4 = spark.sql(
          """
            |select
            |*,date_sub(from_unixtime(unix_timestamp(),'yyyy-MM-dd'),1) as time
            |from (
            |select
            |url as url,
            |count(*) as count
            |from access
            |group by url) t
            |order by t.count desc limit 5
          """.stripMargin)

          //展示结果数据
        result4.show()

          //保存结果数据到mysql表中
        //result4.write.jdbc(url,"t_url",properties)

     //todo:8.5 求各个请求方式出现的次数
        val result5 = spark.sql(
          """
            |select
            |date_sub(from_unixtime(unix_timestamp(),'yyyy-MM-dd'),1) as time,
            |method as method,
            |count(*) as count
            |from access
            |group by method
          """.stripMargin)

        //展示结果数据
        result5.show()

        //保存结果数据到mysql表中
        //result5.write.jdbc(url,"t_method",properties)


    spark.stop()
  }
}

控制台如图:

sparkSQL相关应用案例_第11张图片

查看数据库:

sparkSQL相关应用案例_第12张图片

 

你可能感兴趣的:(sparkSQL相关应用案例)