最近做一个oracle项目迁移工作,跟着spark架构师学着做,进行一些方法的总结。

  1、首先,创建SparkSession对象(老版本为sparkContext)

  val session = SparkSession.builder().appName("app1").getOrCreate()

  2、数据的更新时间配置表,选用mysql,就是说每次结果数据计算写入mysql后,还会将此次数据的更新时间写入数据配置表。 那么在代码里,需要创建配置表的case class,配置与构造数据库schema信息,url,用户名密码等,随后根据配置表中的不同app进行数据的过滤。

  val appId = "1"

  case class DBInformation(url:Stirng,schema:String,user:String,passwd:String)

  val mysqlDB = DBInformation("jdbc:mysql://....",schema,user,passowrd)

  val tableName = mysqlDB.schema + "." + name

  val props = new Properties()

  props.setProperty("user",mysqlDB.user)

  props.setProperty("password",mysqlDB.passwd)

  props.setProperty(JDBCOptions.JDBC_DRIVER_CLASS,"com.mysql.jdbc.Driver")

  val record = session.read.jdbc(mysqlDB.url,tableName,props).filter(row => row.getAs[Int]("app_id") == appId).take(1)

  //第一次写入,木有数据

  if(0 == record.size){

    DBInfoMation(null,null,null)

  }else{

    DBInfoMation(record(0).getTimestmap(1),recode(0).getTimestamp(2),recode(0)..getTimestamp(3))  

  3、注册UDF,由于原来是用oracle的语法,现如今转为sparksql,需要注册一些UDF,来兼容原有oracle的函数

  def registerUDF(session:SparkSession) : Unit = {

    session.udf.register("UDF",(value : String,modifieds:Array[String) => {

      val filter = modifieds.filter(_!=null)

      if(!filter.isEmpty){

        filter.max

      }else{

        null

      }

     })

   {

  4、很多计算是需要过往的历史数据的,在第一次初始化的时候,先对历史数据进行缓存。这里有个知识点,会将一直计算的同步数据进行checkPoint落地磁盘,如果发现历史时间在同步时间之后,则加载历史数据,否则就加载同步数据。

  val (updateTime,initData) = if(historyTime.after(syncTime)){

    (historyTime,initFromHistory(tableName))

  } else {

    (syncTime,initFromCheckPoint(syncTime))

  }

  //记录schema

  schema = initData.schema

  //baseData为缓存在内存的数据,并根据数据量进行repartition

  baseData = initData.repartition(numPartitions,_partitionColumns.map(new Column()):_*).rdd.persisit(storageLevel)

  //触发action动作

  baseData.foreach(_=>Unit)

  5、有一种情况,下游三个表要关联生成一张大表,这三张表的数据来源于消息中间件中的三个topic,但是数据可能不是同时到来,那么就需要将历史加载的大表拆根据ID拆分为三个小表,然后逐个append到三个小表上,随后再根据ID关联起来,再组成最终表。

  val table1 = new createUpdatingTable(session,"tableName1",topicConf,numPartitons,...)

  val table2 = new createUpdatingTable (session,"tableName2",topicConf1,numPartitions,...)

  val table3 = new createUpdatingTable(session,"tableName3","topicConf2,numPartitions,...)

  val mergeBaseTable = (session,"mergeTableName",Array(table1,table2,table3),finallyColumn,finallyPartitions...)

  mergeBaseTable.updateAndGetData(Some(genDataFilter(currentTime)))

  //三表拆分与合并

  val tmpPartitionKey = "pd_code"

  if(baseData != null) {

    val oldData = getOldData(baseData,keyDF.rdd,tmpPartitionKey)

    oldDf = session.createDataFrame(oldData,schema)

    .repartition(numPartitions,new Column(tmpPartitionKey))

    .persist(storageLevel)

  }

  val table1 = updateShardTable(oldDf,inDfs(0)...).sparksession.createDataFrame(data,schema)

  val table2 = ....

  val table3 = ....

  

  6、三表key进行合并,通过sql进行三来源表合并

  val keySet = keys.collect()

  val broadcastKeys = session.sparkContext.broadCast(keySet)

  baseData.mapPartitions({iter =>

    val set = broadcastKey.value.toSet

    iter.filter(row=>set.contains(row.getAs[Any](keyCol)))

  },true)

  val sql ="select a.column,b.column,c.column.... from table1 a left join table2 b on a.pd_code = b.pd_code......

  val finallyTable = session.sql(sql)

  7、从历史数据中筛选出此次需要更新的数据(通过ID进行过滤),随后将新数据进行append

  val new Data = baseData.zipPartitions(updateData,true){case(liter,riter)=>

    val rset = new mutable.HashSet[Any]

    for(row <- riter){

      rset.add(row.getAs[Any](keyCol))

    }

    liter.filter(row=>!rset.contains(row.getAs[Any](keyCol))))

    }.zipPartitions(updateData,true){case (liter,riter)=>

      liter++riter

    }.persisit(storageLevel)

  

sparksql工程小记的更多相关文章

  1. IDEA引入Gradle工程小记

    1.首先IDEA要在该工程Settings中配置本地安装的Gradle,配好其home目录,注意目录到根目录即可,不要到bin一级,否则提示错误,无法使用: 2.配置好后会自动侦测Gradle项目,点 ...

  2. 工程优化暨babel升级小记

    小记背景 随着业务代码的增多,项目代码的编译时长也在增多,遂针对这个痛点在dev下做些优化 第一部分:优化dev编译时间 这里优化的主要思路是在dev环境下,单独出来一个dll配置文件,将项目中的部分 ...

  3. 小记--------sparksql和DataFrame的小小案例java、scala版本

    sparksql是spark中的一个模块,主要用于进行结构化数据的处理,他提供的最核心的编程抽象,就是DataFrame.同时,sparksql还可以作为分布式的sql查询引擎. 最最重要的功能就是从 ...

  4. KEIL工程中头文件包含的一些小记

    @2018-4-25 11:02:27 > 源文件包含自身头文件无须指出其路径

  5. linux 下cmake 编译 ,调用,调试 poco 1.6.0 小记

    上篇文章 小记了: 关于 Poco::TCPServer框架 (windows 下使用的是 select模型) 学习笔记. http://www.cnblogs.com/bleachli/p/4352 ...

  6. 开发Android系统内置应用小记

    Android系统内置应用可以使用更多的API.更高的权限,与开发普通应用最大的差别在于编译,内置应用编译需要用到Android.mk文件.下面是我在开发过程中的一些小记. 1.在AndroidMai ...

  7. Cocos2d-x项目移植到WinRT/Win8小记

    Cocos2d-x项目移植到WinRT/Win8小记 作者: K.C. 日期: 11/17/2013 Date: 2013-11-17 23:33 Title: Cocos2d-x项目移植到WinRT ...

  8. Cocos2d-x项目移植到WP8小记

    Cocos2d-x项目移植到WP8小记 作者: K.C. 日期: 10/24/2013 Date: 2013-10-24 00:33 Title: Cocos2d-x项目移植到WP8小记 Tags: ...

  9. xcode6制作IOS .a静态库小记

    xcode6制作IOS .a静态库小记 创建iOS静态库 简单写个打印的代码 编码完成之后,直接Run就能成功生成.a文件了,选择 xCode->Window->Organizer-> ...

随机推荐

  1. 怎么看vue版本

    查看vue版本号是 vue -V 而不是npm vue -v ,npm vue -v 等同于npm -v vue -V: 后面那个V是大写的.

  2. Codeforces 899 F. Letters Removing (二分、树状数组)

    题目链接:Letters Removing 题意: 给你一个长度为n的字符串,给出m次操作.每次操作给出一个l,r和一个字符c,要求删除字符串l到r之间所有的c. 题解: 看样例可以看出,这题最大的难 ...

  3. Java数据持久层框架 MyBatis之API学习十(Logging详解)

    对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...

  4. JavaScript URL传值过程中遇到的问题及知识点总结

    JavaScript URL传值过程中遇到的问题及知识点总结 Web系统开发过程中经常用到URL进行传值,刚刚接触时不太会解析,会出现中文乱码问题等. 1.父子页面之间的传值(在一个页面中以加载ifr ...

  5. programing

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  6. Hystrix-request cache(请求缓存)

    开启请求缓存 请求缓存在run()和construce()执行之前生效,所以可以有效减少不必要的线程开销.你可以通过实现getCachekey()方法来开启请求缓存. package org.hope ...

  7. junit4X系列源码--总体介绍

    原文出处:http://www.cnblogs.com/caoyuanzhanlang/p/3530267.html.感谢作者的无私分享. Junit是一个可编写重复测试的简单框架,是基于Xunit架 ...

  8. Servlet和web服务器关系

    前面的博客我详细的罗列了下Servlet的常用的类和接口,然后在前面的前面我类似tomcat模拟了一套web服务器,这里来做一个统一的整理,这样子可以更好的把握Servlet,也可以更好的了解下web ...

  9. wer

    概述 快速入门流程: 使用叮当扫码产品请遵循以下操作步骤: 1. 新建项目信息 2. 新建产品信息 3. 添加发货产品 4. 发货 5. 收货 (具体使用操作请查看详细的使用说明) 文档目的: 本文档 ...

  10. Linux防止ARP攻击的一些方法

    方法一,最常用的绑定网关 一般服务器的网关是不会变动的,且vps也适用. 一.查看当前网关 [root@local@xiaohuai ~]# arp -a ? (218.65.22.122) at 8 ...