Spark写MySQL字段数据类型被覆盖问题

问题背景

经过Spark处理之后的数据,需要写到MySQL在web页面进行展示。
 

遇到的问题

因为考虑到写入MySQL中的字段类型,需要提前在MySQL创建好对应的表。并通过JDBC将DataFrame中的内容写入到MySQL。

最初尝试写入MySQL的代码如下:

val df: Dataframe = ... 
df
	.coalesce(2)
	.write
	.mode("overwrite")
	.jdbc(url, "rcc.cr_second_credit_report",  props)

程序是跑成功了,但是到MySQL里面查看数据,发现之前创建的表结构已经被覆盖了,也不是原来的数据类型,都是DataFrame带过来的数据类型,可以说是一团乱。

之后查找原因,发现是DataFrameWriter在SaveMode.Overwrite 模式下写JDBC时,会有一个选项"truncate",默认值是"false"。在默认值情况下,DataFrame写入MySQL会先drop掉已存在的表,然后再根据要写入的DataFrame信息推断出新的建表语句,并create table。明白了这个,也就不难理解,为什么我们明明已经创建好了表却还是被覆盖掉的原因了。
 

解决方法

解决方法很简单,就是把选项"truncate"设置为"true"。设置为"true"之后,在通过SaveMode.Overwrite 模式写JDBC时,就会使用"TRUNCATE TABLE"代替"DROP TABLE",也就是只会删除已存在表的数据,并不会删除表结构。

代码如下:

val df: Dataframe = ... 
df
	.coalesce(2)
	.write
	.mode("overwrite")
	.option("truncate", "true") //设置为true
	.jdbc(url, "rcc.cr_second_credit_report",  props)

不过也要注意:在不同的DBMS中"TRUNCATE TABLE"的作用也是不相同的,所以使用这样选项也并不总是安全的。MySQLDialect, DB2Dialect, MsSqlServerDialect, DerbyDialect,和OracleDialect是支持这个选项的,而 PostgresDialect和默认的JDBCDirect是不支持的。对于那些未知和不支持的JDBCDirect,如果使用了选项"truncate",将会被忽略,不起作用。
 
 

参考

  1. https://issues.apache.org/jira/browse/SPARK-16463
  2. https://github.com/apache/spark/blob/master/sql/core/src/main/scala/org/apache/spark/sql/DataFrameWriter.scala
A&F
发布了14 篇原创文章 · 获赞 3 · 访问量 4937

猜你喜欢

转载自blog.csdn.net/lovetechlovelife/article/details/103833624
今日推荐