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
發佈了14 篇原創文章 · 獲贊 3 · 訪問量 3914
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章