sparkSQL实例_flink sql

sparkSQL实例_flink sql记一次SparkSqlETL过程需求:1)input:json日志2)ETL:根据IP解析出省份,城市3)stat:地区分布指标计算,满足条件的才算,满足条件的赋值为1,不满足的赋值为0(如下图)将统计结果写入MySQL中。(就比如说这个广告请求要满足requestmode=1和processnode=3这两个条件)valspark=SparkSessi…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

记一次SparkSql ETL 过程

需求说明

1)input:json日志
2)ETL:根据IP解析出 省份,城市
3)stat: 地区分布指标计算,
满足条件的才算,满足条件的赋值为1,不满足的赋值为0 (如下图)
将统计结果写入MySQL中。
(就比如说这个广告请求要满足 requestmode=1 和 processnode =3 这两个条件)在这里插入图片描述

代码分析

val spark = SparkSession.builder().master("local[2]").appName("LogApp").getOrCreate()
    import spark.implicits._
    val inputDF = spark.read.json("inputdata/data-test.json")
    inputDF.printSchema()

 	// ETL: 一定保留原有的数据 最完整 而且要落地 (理由:要是数据出错好重新计算)
    val newDF = inputDF.withColumn("province", MyUDF.getProvince(inputDF.col("ip")))
     .withColumn("city", MyUDF.getCity($"ip"))//自定义udf 函数
     .write.format("parquet")
     .mode(SaveMode.Overwrite)
     .save("outparquet") // 最好保存parquet格式 (spark默认就是parquet + snappy)

	 // 计算 重新去读取etl之后的数据源 
    val parquetDF = spark.read.parquet("outparquet/xxx.snappy.parquet")
    parquetDF.printSchema()
    parquetDF.show(5)
    parquetDF.createOrReplaceTempView("log")
    
	//业务SQL
val areaSQL01 = "select province,city, " +
      "sum(case when requestmode=1 and processnode >=1 then 1 else 0 end) origin_request," +
      "sum(case when requestmode=1 and processnode >=2 then 1 else 0 end) valid_request," +
      "sum(case when requestmode=1 and processnode =3 then 1 else 0 end) ad_request," +
      "sum(case when adplatformproviderid>=100000 and iseffective=1 and isbilling=1 and isbid=1 and adorderid!=0 then 1 else 0 end) bid_cnt," +
      "sum(case when adplatformproviderid>=100000 and iseffective=1 and isbilling=1 and iswin=1 then 1 else 0 end) bid_success_cnt," +
      "sum(case when requestmode=2 and iseffective=1 then 1 else 0 end) ad_display_cnt," +
      "sum(case when requestmode=3 and processnode=1 then 1 else 0 end) ad_click_cnt," +
      "sum(case when requestmode=2 and iseffective=1 and isbilling=1 then 1 else 0 end) medium_display_cnt," +
      "sum(case when requestmode=3 and iseffective=1 and isbilling=1 then 1 else 0 end) medium_click_cnt," +
      "sum(case when adplatformproviderid>=100000 and iseffective=1 and isbilling=1 and iswin=1 and adorderid>20000 then 1*winprice/1000 else 0 end) ad_consumption," +
      "sum(case when adplatformproviderid>=100000 and iseffective=1 and isbilling=1 and iswin=1 and adorderid>20000 then 1*adpayment/1000 else 0 end) ad_cost " +
      "from log group by province,city"
    spark.sql(areaSQL01).createOrReplaceTempView("area_tmp")

    val areaSQL02 = "select province,city, " +
      "origin_request," +
      "valid_request," +
      "ad_request," +
      "bid_cnt," +
      "bid_success_cnt," +
      "bid_success_cnt/bid_cnt bid_success_rate," +
      "ad_display_cnt," +
      "ad_click_cnt," +
      "ad_click_cnt/ad_display_cnt ad_click_rate," +
      "ad_consumption," +
      "ad_cost from area_tmp " +
      "where bid_cnt!=0 and ad_display_cnt!=0"

	// 写入MySQL (上一篇博客有介绍)
    val config = ConfigFactory.load()
    val url = config.getString("db.default.url")
    val user = config.getString("db.default.user")
    val password = config.getString("db.default.password")   

    spark.sql(areaSQL02)
      .write.format("jdbc")
      .option("url", url)
      .option("dbtable", "sparksql_test")
      .option("user", user)
      .option("password", password)
      .mode(SaveMode.Overwrite)
      .save()

       spark.stop()

Jetbrains全家桶1年46,售后保障稳定

自定义udf 函数代码

object MyUDF { 
   

  import org.apache.spark.sql.functions._

  def getProvince = udf((ip:String)=>{ 
   
    val cityInfo = IPUtil.getCityInfo(ip)
    val splits = cityInfo.split("\\|")
    var city = "未知"
    if (splits.length == 5){ 
   
      city = splits(2)
    }
    city

  })


  def getCity = udf((ip:String)=>{ 
   
    val cityInfo = IPUtil.getCityInfo(ip)
    val splits = cityInfo.split("\\|")
    var city = "未知"
    if (splits.length == 5){ 
   
      city = splits(3)
    }
    city
  })

}

调优

① ETL 落地过程中应该调用coalesce() 防止产生多个小文件

 val newDF = inputDF.withColumn("province", MyUDF.getProvince(inputDF.col("ip")))
      .withColumn("city", MyUDF.getCity($"ip"))
      .coalesce(1)
     .write.format("parquet").mode(SaveMode.Overwrite).save("outparquet")

② spark.conf.set(“spark.sql.shuffle.partitions”,“400”) 修改SparkSql shuffle task数量,默认是200
在这里插入图片描述

总结

ETL过程:
input:json
清洗 ==> ODS 大宽表 HDFS/Hive/SparkSQL
output: 列式存储 ORC/Parquet (列式存储) (为啥要用这两种? 因为ETL清洗出来的是全字段,我们不可能使用到全部字段,所以采用列式存储,用到几列就获取几列,这样就能减少I/O,性能大大提升)

Stat
==> 一个非常简单的SQL搞定
==> 复杂:多个SQL 或者 一个复杂SQL搞定

列式:ORC/Parquet
特点:把每一列的数据存放在一起
优点:减少IO 需要哪几列就直接获取哪几列
缺点:如果你还是要获取每一行中的所有列,那么性能比行式的差

行式:MySQL
一条记录有多个列 一行数据是存储在一起的
优点:
你每次查询都使用到所有的列
缺点:
大宽表有N多列,但是我们仅仅使用其中几列

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/223422.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Eclipse tomcat插件

    Eclipse tomcat插件

    2021年9月10日
    63
  • javawebday30(验证码在客户端 用当前时间来请求下一张图片 VerifyCode代码)[通俗易懂]

    javawebday30(验证码在客户端 用当前时间来请求下一张图片 VerifyCode代码)[通俗易懂]页面运行servlet500错误信息tomcat报错卡住可能是因为映射错误即web.xml中的问题405post改成get方法如果出现不支持post提交可能需要修改表单中的提交方式VerifyCode.javapublicclassVerifyCode{privateintw=70;privateinth=35;…

    2022年7月15日
    16
  • ssdp协议 upnp_SSDP,简单服务发现协议

    ssdp协议 upnp_SSDP,简单服务发现协议SSDP简单服务发现协议,是应用层协议,是构成UPnP(通用即插即用)技术的核心协议之一。它为网络客户端(networkclient)提供了一种发现网络服务(networkservices)的机制,采用基于通知和发现路由的多播方式实现。SSDP多播地址:239.255.255.250:1900(IPv4),FF0x::C(IPv6)两种类型的SSDP请求消息会通过SSDP多播地址发送:1….

    2022年10月11日
    5
  • 工业相机与镜头选型方法(含实例)

    工业相机与镜头选型方法(含实例)详细介绍了工业相机的分类、参数、相机选型方法以及镜头的参数、镜头选型方法,并应用在实际案例上。

    2022年5月18日
    55
  • 搭建自己的git服务器_自建服务器

    搭建自己的git服务器_自建服务器在服务器端:新建一个空git仓库sudogitinit–baresample.gitsudochown-Rgit:gitsample.git在本地:添加remotegitremoteaddmyservergit@server_ip:/path-to-git-repo把本地内容push上去gitadd.gitcommit-m”xxx”…

    2022年10月5日
    5
  • 【软件测试】测试用例八要素

    【软件测试】测试用例八要素目录测试用例八要素1.测试用例编号2.测试模块3.测试用例标题4.重要级别5.预置条件6.测试输入7.操作步骤8.预期输出测试用例额外的要素1.用例设计者2.用例设计日期3.用例版本号4.对应的开发人员5.测试类型测试用例八要素1.测试用例编号编号是由字母和数字组合而成的,用例的编号应该具有唯一性,易识别性,有且于其和测试结果、错误报告等其他文档的链接。这样看到编号就可以知道是做的什么测试,测试的对象是什么,也方…

    2022年6月28日
    32

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号