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 绝对值,有 ...
随机推荐
- PHP重命名文件夹下的文件后缀名
PHP重命名文件夹下的文件后缀名<pre> public function zhuanhouzuiming(){ $lujings='upload/'; $filesnames = sca ...
- Java核心技术-读书笔记
基本语法 Java中的所有函数都属于某个类的方法 Java没有任何无符号的int.long.short 或 byte 类型 浮点数值不适用于无法接受舍入误差的金融计算中,比如2.0-1.1不会输出想要 ...
- Shuffle an Array (水塘抽样)
随机性问题 水塘抽样算法可保证每个样本被抽到的概率相等 使用场景:从包含n个项目的集合S中选取k个样本,其中n为一很大或未知的数量,尤其适用于不能把所有n个项目都存放到主内存的情况 Knuth洗牌算法 ...
- npm install 报错 error Unexpected end of JSON input while parsing near '...sShrinkwrap":false,"d' 解决办法
npm install 报错 : error Unexpected end of JSON input while parsing near '...sShrinkwrap":false,& ...
- PHP 将字符串中的数字转化为数组
$str ='现在是2019年11月18日下午17点25分';$result='';$arr=[];for($i=0;$i<strlen($str);$i++){ if(is_numeric($ ...
- C基本语法
分号 ; 在C程序中,分好是语句结束符,每个语句必须以分好结束,它表明一个逻辑实体的结束 例如: printf("Hello, World! \n"); ; 注释 // 单行注释 ...
- C语言向txt文件写入当前系统时间(Log)
程序实现很简单,涉及到的只有两个知识点. 1.文件最最基本的打开关闭: 2.系统时间的获取. 代码是在VS2019环境下编写的,部分函数在其他编译器中会无法识别.这个就只能需要自己去查找对应的函数简单 ...
- 在 flutter 上使用 c 代码 - (一) 有源码的项目
在 flutter 的 1.10.x 后的分支, dart:ffi 被并入 flutter, 现在 flutter 中也可以使用 ffi 了. 这东西是啥玩意呢, 就是让 dart 可以直接调用 c/ ...
- 如何通过 IntelliJ IDEA 来提升 Java8 Stream 的编码效率
本文翻译整理自:https://winterbe.com/posts/2015/03/05/fixing-java-8-stream-gotchas-with-intellij-idea 作者:@Wi ...
- Web API 授权筛选器
方式一.全局认证 public static class WebApiConfig { public static void Register(HttpConfiguration config) { ...