利用SparkSQL(java版)将离线数据或实时流数据写入hive的用法及坑点
1. 通常利用SparkSQL将离线或实时流数据的SparkRDD数据写入Hive,一般有两种方法。第一种是利用org.apache.spark.sql.types.StructType和org.apache.spark.sql.types.DataTypes来映射拆分RDD的值;第二种方法是利用rdd和Java bean来反射的机制。下面对两种方法做代码举例
2. 利用org.apache.spark.sql.types.StructType和org.apache.spark.sql.types.DataTypes来映射拆分RDD的值
JavaRDD<Row> resultRdd = rdd.map(new Function<String[], Row>() {
@Override
public Row call(String[] line) throws Exception {
if (line != null && line.length > 0) {
return helper.createRow(line);
}
return null;
}
});
StructType structType = helper.createSchame();
Dataset<Row> dataFrame = session.createDataFrame(resultRdd, structType);
DataFrameWriter<Row> writer = dataFrame.coalesce(1).write().format(TableHelperInter.TABLE_FORMAT_TYPE).mode(SaveMode.Append);
String tableName = hiveDataBaseName + "." + helper.getTableName();
writer.insertInto(tableName);
这种方法的有点是写入简单,不必去考虑字段映射有误,但缺点是需要去写一个TableHelperInter,而且这种方式对字段的类型要求严格,在做字段类型和字段校验时比对时一旦字段过多会及其复杂,所以不推崇这种写法
3. 利用rdd和Java bean来反射
来一个完整的程序
public class SparkSQLTest {
public static void main(String[] args) {
SparkConf conf = new SparkConf().setMaster("yarn").setAppName("SparkSQL_test");
JavaSparkContext sc = new JavaSparkContext(conf);
String line = "1102,jason,20,male,15927384023,developer,col7,col8,col9,col10,col11,col12,col13,col14,col15,col16,col17,col18,col19,col20";
String line2 = "1103,jason1,21,male,15927352023,developer1,col7,col8,col9,col10,col11,col12,col13,col14,col15,col16,col17,col18,col19,col20";
List<String> list = new ArrayList<String>();
list.add(line);
list.add(line2);
JavaRDD<String> rdd = sc.parallelize(list);
JavaRDD<Person> rddResult = rdd.map(new Function<String, Person>() {
@Override
public Person call(String s) throws Exception {
String[] message = s.split(",");
Person person = new Person();
person.setNo(message[0]);
person.setName(message[1]);
person.setAge(message[2]);
person.setGender(message[3]);
person.setPhone(message[4]);
person.setJob(message[5]);
person.setCol7(message[6]);
person.setCol8(message[7]);
person.setCol9(message[8]);
person.setCol10(message[9]);
person.setCol11(message[10]);
person.setCol12(message[11]);
person.setCol13(message[12]);
person.setCol14(message[13]);
person.setCol15(message[14]);
person.setCol16(message[15]);
person.setCol17(message[16]);
person.setCol18(message[17]);
person.setCol19(message[18]);
person.setCol20(message[19]);
person.setCreate_time_p(DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDate.now()));
return person;
}
});
//这行代码必须在实例SparkSession不然会出错
SparkSession.clearDefaultSession();
SparkSession session = SparkSession.builder()
.config("hive.metastore.uris", "localhost:9083")
.config("spark.sql.warehouse.dir", "/apps/hive/warehouse")
.config("hive.exec.dynamic.partition", true)
.config("spark.sql.sources.partitionColumnTypeInference.enabled", false)
.config("hive.exec.dynamic.partition.mode", "nonstrict")
.enableHiveSupport()
.getOrCreate();
Dataset dataset = session.createDataFrame(rddResult,Person.class);
dataset.registerTempTable("person_temp_table");
session.sql("insert into qwrenzixing.person_table20 partition (create_time_p="+DateTimeFormatter.ofPattern("yyyyMMdd")
.format(LocalDate.now())+") select no,name,age,gender,phone,job,col7,col8,col9,col10,col11,col12,col13,col14,col15,col16,col17,col18,col19,col20 from person_temp_table");
}
}
这种方法比较简洁,为了避免去做繁琐的字段比对和校验。可以将字段类型以string写入hive。同时通过SparkSession操作SQL的方法是spark2.0后的。这里是将dataset写成一张临时表,再将临时表的值查询出来insert into到hive表中。但将DataSet通过SparkSQL写成一张临时表的操作,Spark原生提供了四个关于这种操作API
dataset.registerTempTable("temp_table");
dataset.createGlobalTempView("temp_table");
dataset.createOrReplaceTempView("temp_table");
dataset.createTempView("temp_table");
4. 关于这四个将DataSet写成一张临时表的作用和坑点
1>. dataset.registerTempTable("temp_table")这个方法建议在离线,批处理中使用,在实时流式计算中会导致后续写入hive值与字段不匹配乱序的问题
2>. dataset.createGlobalTempView("temp_table")这个方法是创建一个全局临时表,意思就是别的spark-submit也可以用,这种场景很少,而且无法用在实时流式计算中,因为创建一次表后不能再创建会包表已经存在的错误
3>. dataset.createOrReplaceTempView("temp_table");这个其实比较好理解,如果存在就覆盖
4>. dataset.createTempView("temp_table"); 这个方法当spark程序没有结束时不能重复创建
这里的创建临时表在spark程序结束后临时表不存在,所以spark streaming程序要特别注意用法
5. 关于Spark SQL的一个坑点
在mysql中insert into有两种方式
INSERT INTO table_name VALUES (value1, value2,....)
INSERT INTO table_name (column1, column2,...) VALUES (value1, value2,....)
要注意第二种写法在SparkSQL会报错,SparkSQL不支持这种写法,只支持第一种写法。这个是为什么其实也很好理解,每个人想法不一样。第一次使用要避免这个坑点
最后附上我在利用SparkSQL将kafka数据写入hive的重要环节的代码:
String tableName = hiveDataBaseName + ".test_data";
Dataset dataFrame = session.createDataFrame(resultRdd, SJGJEntity.class);
// createOrReplaceTempView API方式将数据写入hive 不存在值与字段名错乱的问题
dataFrame.createOrReplaceTempView("temp_table");
session.sql("insert into " + tableName + " partition(create_time_p=" + DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDate.now())
+ ") select base_name,base_num,serviceCode,phoneno,called_phoneno,call_time,call_longth,lac,ci,xpoint,ypoint,imei,imsi,insert_time,call_address," + "source_table,mark_type,companyId,type,createKafkaTime from temp_table");
利用SparkSQL(java版)将离线数据或实时流数据写入hive的用法及坑点的更多相关文章
- kafka实时流数据架构
初识kafka https://www.cnblogs.com/wenBlog/p/9550039.html 简介 Kafka经常用于实时流数据架构,用于提供实时分析.本篇将会简单介绍kafka以及它 ...
- java版gRPC实战之四:客户端流
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- java版gRPC实战之五:双向流
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- 大数据-07-Spark之流数据
摘自 http://dblab.xmu.edu.cn/blog/1084-2/ 简介 DStream是Spark Streaming的编程模型,DStream的操作包括输入.转换和输出. Spark ...
- 利用AJAX JAVA 通过Echarts实现豆瓣电影TOP250的数据可视化
mysql表的结构 数据(数据是通过爬虫得来的,本篇文章不介绍怎么爬取数据,只介绍将数据库中的数据可视化): 下面就是写代码了: 首先看一下项目目录: 数据库层 业务逻辑层 pac ...
- Java后端开发工程师是否该转大数据开发?
撰写我对java后端开发工程师选择方向的想法,写给在java后端选择转方向的人 背景 看到一些java开发工程师,对java后端薪酬太悲观了.认为换去大数据领域就会高工资.觉得java后端没有前途.我 ...
- Hadoop! | 大数据百科 | 数据观 | 中国大数据产业观察_大数据门户
你正在使用过时的浏览器,Amaze UI 暂不支持. 请 升级浏览器 以获得更好的体验! 深度好文丨读完此文,就知道Hadoop了! 来源:BiThink 时间:2016-04-12 15:1 ...
- GoldenGate实时投递数据到大数据平台(3)- Apache Flume
Apache Flume Flume NG是一个分布式.可靠.可用的系统,它能够将不同数据源的海量日志数据进行高效收集.聚合,最后存储到一个中心化数据存储系统中,方便进行数据分析.事实上flume也可 ...
- 使用Oracle Stream Analytics 21步搭建大数据实时流分析平台
概要: Oracle Stream Analytics(OSA)是企业级大数据流实时分析计算平台.它可以通过使用复杂的关联模式,扩充和机器学习算法来自动处理和分析大规模实时信息.流式传输的大数据可以源 ...
随机推荐
- elasticsearch 6.x 安装search guard
前言 es之前版本一直无用户验证功能,不过官方有提供一x-pack,但是问题是付费.在es的6.3.2版本中,已经集成了x-pack,虽然es团队已经对x-pack开源,但是在该版本中如果需要使用到安 ...
- git小乌龟图标不显示 windows系统
1.修改注册表[windows + R 输入 regedit]进入注册信息,按照步骤找到 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Curre ...
- iview select下拉框的蜜汁小坑
前言 最近使用iview的select下拉选择器,遇到一个很神奇的问题:选中下拉框里面的一个值,但是再去点下拉框的时候就只剩刚才选中的数据了.感觉应该是插件把刚才选中的数据当做的搜索条件,所以需要做的 ...
- 一张图告诉你js为什么要加分号
当js代码被压缩或者通过其他方式改变你的编码结构时,分号能够给编译器和解析器提供精准的语句拆分. 如图中m 和 c 的例子就能解释为什么这样做.
- 【LeetCode 31】下一个排列
题目链接 [题解] 从右往左找第一个下降的位置i(即满足nums[i]<nums[i+1]); 然后在[i+1..len-1]这个区间里面找到一个最大的下标k,使得nums[k]>nums ...
- Python面向对象 杂篇(后记)
异常处理 什么是异常: 我们在调试程序时,常常会因为各种报错信息导致程序无法运行,异常也是一个对象,用来表示错误.我们可以捕捉异常,并做相应处理,从而增加代码的友好程度. 异常处理: ...
- 【已转移】【缓存与性能优化】一篇文章搞掂:Redis
本文篇幅较长,建议合理利用右上角目录进行查看(如果没有目录请刷新). 一.什么是Redis 全称: Remote Dictionary Server 远程字典服务器 实质: 一个缓存结构服务器或数据结 ...
- java集合框架面试要点整理
- Python单元测试示例
这是使用单元测试框架unittest进行的单元测试,并输出测试结果. 首先定义一个类,三个方法.第一个方法是判断两个字符串是否相等,第二个方法是判断结果为真:第三个方法也是判断两个字符串相等. 然后是 ...
- Struts1.3——Struts标签
1.struts标签的介绍 Struts框架提供了一组非常丰富的框架组件,同时也提供了一组标签库用于和这些组件交互,主要介绍以下三类: html标签 bean标签 logic标签 2.Html标签库 ...