本篇博文的主要内容:
1、分析Spark读写Oracle方法
2、DataFrame数据写入Oracle
3、Hive数据写入Oracle
DataFrame是在Spark1.3.0中推出的新的api,它借鉴了R语言DataFrame的一些优点,同时,扩充了Spark处理大规模结构化数据的能力。作为Spark初学者,在通过学习使用Spark读写RDBMS数据的过程中,遇到了一系统的问题,查阅了大量文章,得到了一一解决,现将Spark读写oracle数据库的总结分享给大家,与大家共勉。如果文章中有错误的地方,希望大家及时指正,谢谢合作!
1、Spark读写Oracle方法分析
目前,Spark在读写关系型数据表时提供了DataFrameReader和DataFrameWriter等类。在读取Oracle数据库时,通过测试(具体实现将在下面描述),可以根据官网提供的读取数据库方式获取数据。但是在写Oracle数据库时,会报“no suitable driver found”异常。这是因为DataFrameWriter的jdbc方法目前还不能支撑写oracle数据库。(个人理解,目前作者尚未解决该问题)
考虑使用JdbcUtils.saveTable的方式写Oracle数据库,但是报“java.sql.SQLException: ORA-00902: invalid datatype”异常。
查阅OracleDialect.scala源码
private case object OracleDialect extends JdbcDialect {
override def canHandle(url: String): Boolean = url.startsWith("jdbc:oracle")
override def getCatalystType(
sqlType: Int, typeName: String, size: Int, md: MetadataBuilder): Option[DataType] = {
// Handle NUMBER fields that have no precision/scale in special way
// because JDBC ResultSetMetaData converts this to 0 procision and -127 scale
// For more details, please see
// https://github.com/apache/spark/pull/8780#issuecomment-145598968
// and
// https://github.com/apache/spark/pull/8780#issuecomment-144541760
if (sqlType == Types.NUMERIC && size == 0) {
// This is sub-optimal as we have to pick a precision/scale in advance whereas the data
// in Oracle is allowed to have different precision/scale for each value.
Option(DecimalType(DecimalType.MAX_PRECISION, 10))
} else {
None
}
}
}
可以发现,OracleDialect 覆写了getCatalystType(该方法用于读取Oracle数据库时数据类型的转换),但是没有覆写getJDBCType(该方法用于写Oracle数据库时数据类型的转换),因此,在写Oracle数据库时,由于找不到可用的数据类型方言的转换,导致Oracle数据库无法识别某些数据类型。需要覆写getJDBCType方法,将数据类型转换为