大数据-SparkSQL(五)

                              大数据-SparkSQL(五)

sparksql中自定义函数

自定义UDF函数

代码开发

package com.kaikeba.sql

import org.apache.spark.sql.api.java.UDF1
import org.apache.spark.sql.types.StringType
import org.apache.spark.sql.{DataFrame, SparkSession}

//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函数

    //小写转大写
    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)


    //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整合hive

步骤

  • 1、需要把hive安装目录下的配置文件hive-site.xml拷贝到每一个spark安装目录下对应的conf文件夹中
  • 2、需要一个连接mysql驱动的jar包拷贝到spark安装目录下对应的jars文件夹中
  • 3、可以使用spark-sql脚本 后期执行sql相关的任务

启动脚本

spark-sql \
--master spark://node01:7077 \
--executor-memory 1g \
--total-executor-cores 4 \
--conf spark.sql.warehouse.dir=hdfs://node01:8020/user/hive/warehouse

应用场景

#!/bin/sh
#定义sparksql提交脚本的头信息
SUBMITINFO="spark-sql --master spark://node01:7077 --executor-memory 1g --total-executor-cores 4 --conf spark.sql.warehouse.dir=hdfs://node01:8020/user/hive/warehouse" 
#定义一个sql语句
SQL="select * from default.hive_source;" 
#执行sql语句   类似于 hive -e sql语句
echo "$SUBMITINFO" 
echo "$SQL"
$SUBMITINFO -e "$SQL"

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

需求描述

通过sparksql对用户访问产生点击流日志数据进行分析处理,计算出对应的指标。

代码开发

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

AccessLogUtils

package com.kaikeba.sql.applog

import scala.util.matching.Regex

case 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)指标统计

LogAnalysis

package com.kaikeba.sql.applog

import java.util.Properties

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

/**
  * 日志分析案例
  */
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(四)

下一篇《大数据-Spark调优(一)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值