spark读写Oracle、hive的艰辛之路(二)-Oracle的date类型
近期又有需求为:导入Oracle的表到hive库中;
关于spark读取Oracle到hive有以下两点需要说明:
1、数据量较小时,可以直接使用spark.read.jdbc(orclUrl,table_name,orclProperties)读取,效率应该没什么问题,能很快完成;
2、数据量较大时候,使用spark.read.jdbc(orclUrl,table_name,分区条件,orclProperties)方法,分区读取,该方法可根据分区条件同时多线程读取;原理为在读取Oracle的SQL最后加入where+不同的分区条件;例如oracle 中的id为1~10;分区之后为where id >=1 and id <=5和where id >=6 and id <=10;两个线程同时读取;
源码如下:spark2.2.0;请注意看官方注释
/**
* Construct a `DataFrame` representing the database table accessible via JDBC URL
* url named table using connection properties. The `predicates` parameter gives a list
* expressions suitable for inclusion in WHERE clauses; each one defines one partition
* of the `DataFrame`.
*
* Don't create too many partitions in parallel on a large cluster; otherwise Spark might crash
* your external database systems.
*
* @param url JDBC database url of the form `jdbc:subprotocol:subname`
* @param table Name of the table in the external database.
* @param predicates Condition in the where clause for each partition.
* @param connectionProperties JDBC database connection arguments, a list of arbitrary string
* tag/value. Normally at least a "user" and "password" property
* should be included. "fetchsize" can be used to control the
* number of rows per fetch.
* @since 1.4.0
*/
def jdbc(
url: String,
table: String,
predicates: Array[String],
connectionProperties: Properties): DataFrame = {
assertNoSpecifiedSchema("jdbc")
// connectionProperties should override settings in extraOptions.
val params = extraOptions.toMap ++ connectionProperties.asScala.toMap
val options = new JDBCOptions(url, table, params)
val parts: Array[Partition] = predicates.zipWithIndex.map { case (part, i) =>
JDBCPartition(part, i) : Partition
}
val relation = JDBCRelation(parts, options)(sparkSession)
sparkSession.baseRelationToDataFrame(relation)
}
在实际工作中发现。spark读取Oracle时,Oracle中的date类型并不能得到很好的支持,例如:2018-10-10 23:00格式的时间,在去读取到hive表中之后只剩下了2018-10-10,小时和分钟没了;
可行的解决方案如下:重写java的方言,代码如下:
import org.apache.spark.sql.jdbc.JdbcDialect;
import org.apache.spark.sql.jdbc.JdbcDialects;
import org.apache.spark.sql.jdbc.JdbcType;
import org.apache.spark.sql.types.DataType;
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.MetadataBuilder;
import scala.Option;
import java.sql.Types; public class OracleDateTypeInit {
public static void oracleInit() {
JdbcDialect dialect = new JdbcDialect() { //判断是否为oracle库
@Override
public boolean canHandle(String url) {
return url.startsWith("jdbc:oracle");
} //用于读取Oracle数据库时数据类型的转换
@Override
public Option<DataType> getCatalystType(int sqlType, String typeName, int size, MetadataBuilder md) {
if (sqlType == Types.DATE && typeName.equals("DATE") && size == 0)
return Option.apply(DataTypes.TimestampType);
return Option.empty();
} //用于写Oracle数据库时数据类型的转换
@Override
public Option<JdbcType> getJDBCType(DataType dt) {
if (DataTypes.StringType.sameType(dt)) {
return Option.apply(
new JdbcType("VARCHAR2(255)", Types.VARCHAR));
} else if (DataTypes.BooleanType.sameType(dt)) {
return Option.apply(
new JdbcType("NUMBER(1)", Types.NUMERIC));
} else if (DataTypes.IntegerType.sameType(dt)) {
return Option.apply(
new JdbcType("NUMBER(10)", Types.NUMERIC));
} else if (DataTypes.LongType.sameType(dt)) {
return Option.apply(
new JdbcType("NUMBER(19)", Types.NUMERIC));
} else if (DataTypes.DoubleType.sameType(dt)) {
return Option.apply(
new JdbcType("NUMBER(19,4)", Types.NUMERIC));
} else if (DataTypes.FloatType.sameType(dt)) {
return Option.apply(
new JdbcType("NUMBER(19,4)", Types.NUMERIC));
} else if (DataTypes.ShortType.sameType(dt)) {
return Option.apply(
new JdbcType("NUMBER(5)", Types.NUMERIC));
} else if (DataTypes.ByteType.sameType(dt)) {
return Option.apply(
new JdbcType("NUMBER(3)", Types.NUMERIC));
} else if (DataTypes.BinaryType.sameType(dt)) {
return Option.apply(
new JdbcType("BLOB", Types.BLOB));
} else if (DataTypes.TimestampType.sameType(dt)) {
return Option.apply(
new JdbcType("DATE", Types.DATE));
} else if (DataTypes.DateType.sameType(dt)) {
return Option.apply(
new JdbcType("DATE", Types.DATE));
} else if (DataTypes.createDecimalType()
.sameType(dt)) { //unlimited
/* return DecimalType.Fixed(precision, scale)
=>Some(JdbcType("NUMBER(" + precision + "," + scale + ")",
java.sql.Types.NUMERIC))*/
return Option.apply(
new JdbcType("NUMBER(38,4)", Types.NUMERIC));
}
return Option.empty();
}
};
//注册此方言
JdbcDialects.registerDialect(dialect);
}
}
使用时调用就可以了
//spark直接读取hive之后date类型的数据只剩年月日了,需要转为TimestampType
OracleDateTypeInit.oracleInit()
spark读写Oracle、hive的艰辛之路(二)-Oracle的date类型的更多相关文章
- Oracle中把一个DateTime的字符串转化成date类型。to_date('2016/12/8 18:55:43','yyyy/MM/dd hh24:mi:ss'),
Oracle中把一个DateTime或者该形态字符串转化成date类型. to_date('2016/12/8 18:55:43','yyyy/MM/dd hh24:mi:ss'), 或者: sele ...
- spark读写Oracle、hive的艰辛之路(一)
前两天工作需求,要通过给的几个Oracle的视图把数据入到hive库中,很遗憾,使用的华为云平台的集区环境中并没有sqoop1,当然也并没有sqoop2,所以,想到的解决方案是使用spark读取Ora ...
- Spark 读写hive 表
spark 读写hive表主要是通过sparkssSession 读表的时候,很简单,直接像写sql一样sparkSession.sql("select * from xx") 就 ...
- 大数据学习系列之七 ----- Hadoop+Spark+Zookeeper+HBase+Hive集群搭建 图文详解
引言 在之前的大数据学习系列中,搭建了Hadoop+Spark+HBase+Hive 环境以及一些测试.其实要说的话,我开始学习大数据的时候,搭建的就是集群,并不是单机模式和伪分布式.至于为什么先写单 ...
- HADOOP+SPARK+ZOOKEEPER+HBASE+HIVE集群搭建(转)
原文地址:https://www.cnblogs.com/hanzhi/articles/8794984.html 目录 引言 目录 一环境选择 1集群机器安装图 2配置说明 3下载地址 二集群的相关 ...
- spark2.3.0 配置spark sql 操作hive
spark可以通过读取hive的元数据来兼容hive,读取hive的表数据,然后在spark引擎中进行sql统计分析,从而,通过spark sql与hive结合实现数据分析将成为一种最佳实践.配置步骤 ...
- 使用Spark读写CSV格式文件(转)
原文链接:使用Spark读写CSV格式文件 CSV格式的文件也称为逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号.在本文中的CSV格 ...
- Spark读写ES
本文主要介绍spark sql读写es.structured streaming写入es以及一些参数的配置 ES官方提供了对spark的支持,可以直接通过spark读写es,具体可以参考ES Spar ...
- Oracle/Hive/Impala SQL比较1
5 Function 指数据库内置的function,不讨论UDF.另外,操作符都不比较了,区别不大. 5.1 数学函数 功能 Oracle Hive Impala ABS 绝对值,有 ...
随机推荐
- SQL Server ----- 备份数据库 生成(.bak)文件
转移数据库 备份数据库 选中数据库 进入后界面如图 选择合适位置进行备份 注意:选择配置好保存位置的 成功后出现 如果出现错误. 还有一种可能是哪个文件夹中已经有了一个 把文件家中的那个删了 还原 ...
- 递推 + 高精度 --- Tiling
Tiling Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7264 Accepted: 3528 Descriptio ...
- for循环中的switch的break和continue作用范围
for循环中的switch的break和continue作用范围 不空泛的讲理论了,上代码.看下面这个代码: #include <stdio.h> #include <stdlib. ...
- nginx location指令详解
Nginx的HTTP配置主要包括三个区块,结构如下: http { //这个是协议级别 include mime.types; default_type application/octet-strea ...
- BZOJ3926 ZJOI2015诸神眷顾的幻想乡(广义后缀自动机)
对多串建立SAM的一种方法是建trie再对trie建SAM.构造方式分为在线(也即不建trie而是依次插入每个串,或在trie上dfs)和离线(也即建好trie再bfs).其中离线构造与单串的构造方式 ...
- Linux学习笔记之rpm包管理功能全解
0x00 软件包管理器 所有的软件都是由文件格式的程序代码(即源代码),经过编译成为一个可执行二进制文件:对于一个软件来说,其包含二进制程序.库文件.配置文件以及帮助文件.在应用中,每次要安装程序时通 ...
- MongoDB常用数据库命令第二集
=======================基础命令======================= mongo 进入数据库操作界面db 查看当前使用的数据库show dbs 查看当前已经被创建出来的 ...
- Javascript/js 的浅拷贝与深拷贝(复制)学习随笔
js变量的数据类型值分基本类型值和引用类型值. 在ES6(ECMAScript6)以前,基本数据类型包括String.Number.Boolean.Undefined.Null. 基本类型值的复制(拷 ...
- iOS静态库转Framework动态库
参考文章: iOS静态库(.a 和framework) XCode6制作动态及静态Framework 说说iOS中静态库的开发 dyld: Library not loaded: @rpath/ ...
- Node初识
初识Nodejs Node.js的诞生 作者Ryan Dahl 瑞恩·达尔 2004 纽约 读数学博士 2006 退学到智利 转向开发 2009.5对外宣布node项目,年底js大会发表演讲 2010 ...