sparksql工程小记
最近做一个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工程小记的更多相关文章
- IDEA引入Gradle工程小记
1.首先IDEA要在该工程Settings中配置本地安装的Gradle,配好其home目录,注意目录到根目录即可,不要到bin一级,否则提示错误,无法使用: 2.配置好后会自动侦测Gradle项目,点 ...
- 工程优化暨babel升级小记
小记背景 随着业务代码的增多,项目代码的编译时长也在增多,遂针对这个痛点在dev下做些优化 第一部分:优化dev编译时间 这里优化的主要思路是在dev环境下,单独出来一个dll配置文件,将项目中的部分 ...
- 小记--------sparksql和DataFrame的小小案例java、scala版本
sparksql是spark中的一个模块,主要用于进行结构化数据的处理,他提供的最核心的编程抽象,就是DataFrame.同时,sparksql还可以作为分布式的sql查询引擎. 最最重要的功能就是从 ...
- KEIL工程中头文件包含的一些小记
@2018-4-25 11:02:27 > 源文件包含自身头文件无须指出其路径
- linux 下cmake 编译 ,调用,调试 poco 1.6.0 小记
上篇文章 小记了: 关于 Poco::TCPServer框架 (windows 下使用的是 select模型) 学习笔记. http://www.cnblogs.com/bleachli/p/4352 ...
- 开发Android系统内置应用小记
Android系统内置应用可以使用更多的API.更高的权限,与开发普通应用最大的差别在于编译,内置应用编译需要用到Android.mk文件.下面是我在开发过程中的一些小记. 1.在AndroidMai ...
- Cocos2d-x项目移植到WinRT/Win8小记
Cocos2d-x项目移植到WinRT/Win8小记 作者: K.C. 日期: 11/17/2013 Date: 2013-11-17 23:33 Title: Cocos2d-x项目移植到WinRT ...
- Cocos2d-x项目移植到WP8小记
Cocos2d-x项目移植到WP8小记 作者: K.C. 日期: 10/24/2013 Date: 2013-10-24 00:33 Title: Cocos2d-x项目移植到WP8小记 Tags: ...
- xcode6制作IOS .a静态库小记
xcode6制作IOS .a静态库小记 创建iOS静态库 简单写个打印的代码 编码完成之后,直接Run就能成功生成.a文件了,选择 xCode->Window->Organizer-> ...
随机推荐
- 自实现PC端jQuery版轮播图
最近其他项目不是很忙,被安排给公司的官网项目做一个新的页面(之前没接触公司官网项目),其中有一个用到轮播图的地方,最开始想直接用swiper.js插件实现就好了,可是发现官网项目里之前都没有引入过sw ...
- angularjs+ionic+'h5+'实现二维码扫描功能
今天给大家分享一下基于angularjs与ionic框架实现手机二维码扫描的功能.没有用到cordova等任何插件,h5+实现的. 开发工具:hbuilder 首先,需要在hbuilder项目下面的配 ...
- tp5 $_ENV获取不到数据
$_ENV变量是取决于服务器的环境变量的,从不同的服务器上获取的$_ENV变量打印出的结果可能是不同的. php的配置文件php.ini的配置项为:variables_order = "GP ...
- Linux中ctrl+z 、ctrl+c、 ctrl+d区别
ctrl+c,ctrl+d,ctrl+z在linux程序中意义和区别 ctrl+c和ctrl+z都是中断命令,但是他们的作用却不一样. ctrl+c是强制中断程序的执行,,进程已经终止. ct ...
- intellij idea on update action\on frame deactivation ||Servlet 页面不同步问题
当修改servlet源码时,对应的servlet页面即使刷新也不会改变,,,很烦躁 因为xx.java需要编译成xx.class后,再部署到服务器上才可以运行,所以问题就是服务器里的类文件并没有更新. ...
- asp.net -mvc框架复习(10)-基于三层架构与MVC搭建项目框架
一.三种模式比较 1.MVC框架(适合大型项目) (1).V视图 (网页部分) (2).M模型 (业务逻辑+数据访问+实体类) (3).C控制器 (介于M和V之间,起到引导作用) 2.三层架构 (1) ...
- PhoneGap安装手顺
http://docs.phonegap.com/getting-started/1-install-phonegap/desktop/
- 修改ncnn的openmp异步处理方法 附C++样例代码
ncnn刚发布不久,博主在ios下尝试编译. 遇上了openmp的编译问题. 寻找各种解决方案无果,亲自操刀. 采用std::thread 替换 openmp. ncnn项目地址: https://g ...
- JS中数组的常用方法
首先,在开始前我们先了解一下什么是数组. 1.什么是数组? 数组就是一组数据的集合,其表现形式就是内存中的一段连续的内存地址,数组名称其实就是连续内存地址的首地址.说白了它就是将一堆数据按照一定的顺序 ...
- java常用类--与用户互动
运行java的参数: 主方法:public static void main(String[] args){}:为了让JVM可以自由调用main方法,使用public修饰,JVM通过类来调用main方 ...