ETL实践--Spark做数据清洗

上篇博客,说的是用hive代替kettle的表关联。是为了提高效率。

本文要说的spark就不光是为了效率的问题。

1、用spark的原因

(如果是一个sql能搞定的关联操作,可以直接用kettle导原始数据到hive,用hive视图做关联直接给kylin提供数据)

(1)、场景一之前用kettle需要多个转换、关联才能实现数据清洗的操作。

用hive不知道如何进行,就算能进行也感觉繁琐,同时多个步骤必然降低数据时效性。用mr的话也是同样道理太多步骤繁琐不堪。

(2)、一些不能用sql来处理的数据清洗逻辑。比如循环类的,或者是更复杂的处理逻辑。用hive和kettle都不方便解决。

一些其他的原因

(3)、支持的语言多,容易上手,并且之前也学习过一些。

(4)、我公司用的大数据平台上,提供了spark的支持,可以方便的安装和维护,并且可以和现有平台很好的融合(yarn部署方式)。

(5)、效率高。

(6)、刚好公司有需要用到spark streaming。

2、下面是我学习用spark处理业务问题的一个例子。有注释和一些方法的测试。

public class EtlSpark5sp2Demo {

    //3、解码器
//static final Encoder<EcardAccessOutTime> outTimeEncoder = Encoders.bean(EcardAccessOutTime.class);
static final Encoder<EcardAccessInout> inoutEncoder = Encoders.bean(EcardAccessInout.class); public static void main(String[] args) {
SparkSession spark = SparkSession
.builder().master("local")
.appName("Java Spark SQL data sources example")
.config("spark.some.config.option", "some-value")
.getOrCreate(); runJdbcDatasetExample(spark);
spark.stop();
} private static void runJdbcDatasetExample(SparkSession spark) { Properties connectionProperties = new Properties();
connectionProperties.put("user", "root123");
connectionProperties.put("password", "123");
String dbUrl="jdbc:mysql://192.168.100.4:3306/datasql?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8"; //对比java中连接mysql的字符串(标红的是区别,分割字符串是spark识别不了的,要去掉)
//  mysql.url=jdbc:mysql://192.168.100.4:3306/datasql?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=UTF-8
        //1、查询原始数据
final Dataset<Row> allRecord = spark.read()
.jdbc(dbUrl,
"( select a.kid,a.outid,a.ioflag,a.OpDT as 'indate',a.OpDT as 'outdate',a.school_code ,a.faculty_code,a.major_code,a.class_code,a.sex from access_record_inout_temp2 a limit 3000 ) t", connectionProperties); final Dataset<EcardAccessInout> allRecordInout=allRecord.as(inoutEncoder);
         spark提供了把数据集注册成视图,然后用sql的方式对数据集进行处理的功能:如下2、3所示
        //2、将原始数据注册成视图
allRecord.createOrReplaceTempView("view_access_record_inout_temp2");
allRecord.printSchema();//打印数据集结构
        //3、在上面注册的视图上执行sql测试:查询出进入宿舍的记录
        final   Dataset<EcardAccessInout> inRecord  = spark.sql(
" select a.kid,a.outid,a.ioflag,a.school_code,a.faculty_code,a.major_code,a.class_code,a.sex,a.indate,a.outdate " +
" from view_access_record_inout_temp2 a " +
" where a.ioflag = 0 ").as(inoutEncoder);
inRecord.printSchema();
//打印数据集结构
        inRecord.show();

        spark不光提供了针对注册的视图的sql查询。也提供了通过方法来查询数据集的方式:下面是2种方式

        //4、filter用法测试:
        String outid="45723107";
long kid=7516452;
//filter方法能够正常使用
Dataset<Row> list1 = allRecord.filter(allRecord.col("outid").equalTo(outid).and(allRecord.col("kid").gt(kid))).orderBy(allRecord.col("indate"));//.take(1);//
list1.show();
//打印前20条记录


        5、where用法测试

        //where方法能够正常使用
        Dataset<Row> list2 =  allRecord.where("outid = '"+ outid +"'").where("kid > "+ kid +"").orderBy("indate");
list2.show();
//打印前20条记录


        //6、分组取topN:测试::mysql中可以group by 2个字段查询全部的字段。实际返回值是取的分组后的第一条记录。(对应实际业务就按照学号和时间去重,数据当中有重复数据)
            6.1、mysql中的原始sql
                            select a.id,a.outid,g.school_code,g.faculty_code,g.major_code,g.class_code,g.sex,a.OpDT,a.ioflag

from access_record a inner join own_org_student g on a.OutId=g.outid
                               where a.id > ?   group by a.OutId,a.OpDT

 
           6.2、hive和spark都不支持这种操作。他们的做法是一样的。就是通过下面这个sql,用row_number()函数分组,取第一
           final   Dataset<Row> topRecord  = spark.sql(
" select t.kid,t.outid,t.ioflag,t.school_code,t.faculty_code,t.major_code,t.class_code,t.sex,t.indate,t.outdate from (" +
" select a.kid,a.outid,a.ioflag,a.school_code,a.faculty_code,a.major_code,a.class_code,a.sex,a.indate,a.outdate, " +
" row_number() over(partition by outid order by indate) as rowNumber " + //根据行号top
" from view_access_record_inout_temp2 a " +
" where a.ioflag = 0 " +
" ) t where rowNumber =1 "); topRecord.show();//打印前20条记录 //7、循环:合并进入记录和出去的记录
7.1、这里先进行先按照学号分区,再按照时间排序。
Dataset<EcardAccessInout> allRecordSort= allRecordInout.repartition(allRecordInout.col("outid")).sortWithinPartitions(allRecordInout.col("indate"));
        7、循环:合并进入记录和出去的记录(因为已经排序了,本条记录的下一条,如果是正常记录就是出去的记录)
        Iterator<EcardAccessInout> iterator = allRecordSort.toLocalIterator();
List<EcardAccessInout> result=new ArrayList<EcardAccessInout>();
while(iterator.hasNext()){
EcardAccessInout first= iterator.next();
if("0".endsWith(first.getIoflag())){//第一条记录是:进入宿舍的记录
if(iterator.hasNext()){
EcardAccessInout second= iterator.next();
//取比入记录大的最小的一条出记录的时间,作为入记录的出时间。(排序后,后面一条就是最小记录)
if(first.getOutid().endsWith(second.getOutid())&&("1".endsWith(second.getIoflag()))&&first.getIndate().before(second.getIndate())){
first.setOutdate(second.getIndate());
result.add(first);
}
}
}
} //8、处理后的数据写入mysql。这里只是个例子,实际数据应该是写到hdfs,变成hive表
inRecord.write().mode(SaveMode.Append)
.jdbc(dbUrl, "datacenter.access_record_inout_temp10", connectionProperties); } }

ETL实践--Spark做数据清洗的更多相关文章

  1. 苏宁基于Spark Streaming的实时日志分析系统实践 Spark Streaming 在数据平台日志解析功能的应用

    https://mp.weixin.qq.com/s/KPTM02-ICt72_7ZdRZIHBA 苏宁基于Spark Streaming的实时日志分析系统实践 原创: AI+落地实践 AI前线 20 ...

  2. ETL实践--kettle转到hive

    ETL实践--kettle只做源数据的抽取,其他数据转换转到hive上. 1.用hive代替kettle的数据关联的原因 (1).公司之前的数据ELT大量使用了kettle.用kettle导原始数据速 ...

  3. ETL项目2:大数据清洗,处理:使用MapReduce进行离线数据分析并报表显示完整项目

    ETL项目2:大数据清洗,处理:使用MapReduce进行离线数据分析并报表显示完整项目 思路同我之前的博客的思路 https://www.cnblogs.com/symkmk123/p/101974 ...

  4. 数据仓库建模与ETL实践技巧

    数据分析系统的总体架构分为四个部分 —— 源系统.数据仓库.多维数据库.客户端(图一:pic1.bmp) 其中,数据仓库(DW)起到了数据大集中的作用.通过数据抽取,把数据从源系统源源不断地抽取出来, ...

  5. 技术分享丨数据仓库的建模与ETL实践技巧

    摘要:如何搭建数据仓库,在这个过程中都应该遵循哪些方法和原则,项目实践中有哪些技巧. 一.数据仓库的“心脏” 首先来谈谈数据模型.模型是现实世界特征的模拟和抽象,比如地图.建筑设计沙盘,飞机模型等等. ...

  6. 一、ETL实践之数据可视化架构

    开篇心声: 不管是学习新知识,还是遇到各种难题,总能在技术论坛找到经验帖子.一直享受大家提供的帮助,而自己没有任何输出,实在过意不去.我相信技术是经验的交流,思维的碰撞. 这是我一次写技术分享文章,我 ...

  7. Spark面试相关

    Spark Core面试篇01 随着Spark技术在企业中应用越来越广泛,Spark成为大数据开发必须掌握的技能.前期分享了很多关于Spark的学习视频和文章,为了进一步巩固和掌握Spark,在原有s ...

  8. Spark大数据针对性问题。

    1.海量日志数据,提取出某日访问百度次数最多的那个IP. 解决方案:首先是将这一天,并且是访问百度的日志中的IP取出来,逐个写入到一个大文件中.注意到IP是32位的,最多有个2^32个IP.同样可以采 ...

  9. 个推 Spark实践教你绕过开发那些“坑”

    Spark作为一个开源数据处理框架,它在数据计算过程中把中间数据直接缓存到内存里,能大大提高处理速度,特别是复杂的迭代计算.Spark主要包括SparkSQL,SparkStreaming,Spark ...

随机推荐

  1. xml解析(4)

    本节要点: DOM解析方式 SAX解析方式 DOM4J对XML的解析 XML用于将数据组织起来,形成文档用于存储和传输: 更多时候我们需要的是将xml中的数据解析出来,甚至是在程序中动态生成xml. ...

  2. TP3.2.3 接入银联支付

    TP3.2.3 接入银联支付 项目接入银联支付的过程, 在此记录下,希望能帮助开发盆友平坑. 银联SKD链接:https://open.unionpay.com/ajweb/product/newPr ...

  3. 自学Python1.2-环境的搭建:Pycharm及python安装详细教程

    Python几乎可以在任何平台下运行,如我们所熟悉的:Windows/Unix/Linux/Macintosh 一.windows下安装Python 1. 从python官方网站:http://www ...

  4. springMVC学习总结(四)springmvc处理json数据类型以及fastjson的使用

    springMVC学习总结(四)springmvc处理json数据类型以及fastjson的使用 主要内容: 这篇文章主要是总结之前使用springmv接收json的时候遇到的问题,下面通过前台发送a ...

  5. bzoj 1597: [Usaco2008 Mar]土地购买

    Description 农 夫John准备扩大他的农场,他正在考虑N (1 <= N <= 50,000) 块长方形的土地. 每块土地的长宽满足(1 <= 宽 <= 1,000 ...

  6. nginx php上传配置

    .file_uploads 设为On,允许通过HTTP上传文件 2.upload_tmp_dir 文件上传至服务器时用于临时存储的目录,如果没指定,系统会使用默认的临时文件夹(我的机器是/tmp). ...

  7. cp 命令详解

    作用:  cp 指令用于复制文件或目录,如同时指定两个以上的文件或目录,且最后的目的地是一个已经存在的目录, 则它会把前面指定的所有文件或目录复制到此目录下, 若同时指定多个文件或目录, 而最后的目的 ...

  8. 7、树莓派编程;gpio编程;led闪烁

    本博文仅作本人操作过程的记录,留作备忘.自强不息 QQ12226981 1.树莓派接口对照,一定要找到对应的引脚,不要接错了.我画上箭头. 2.安装 下载地址,https://git.drogon.n ...

  9. 字符串MD5加密运算

    public static string GetMd5String(string str)       {           MD5 md5 = MD5.Create();           by ...

  10. JMeter测试HTTPS

    HTTP和HTTPS测试时稍有不同,HTTPS需要加载证书,端口也不一样,操作如下:  1)下载被测网站证书导入 见图为流程: 2)使用JMeter自带的证书 ApacheJMeterTemporar ...