原創文章,謝絕轉載
Spark 2.x自2.0.0發布到目前的2.2.0已經有一年多的時間了,2.x宣稱有諸多的性能改進,相信不少使用Spark的同學還停留在1.6.x或者更低的版本上,沒有升級到2.x或許是由于1.6相對而言很穩定,或許是升級后處處踩坑被迫放棄。
Spark SQL是Spark中最重要的模塊之一,基本上Spark每個版本發布SQL模塊都有不少的改動,而且官網還會附帶一個Migration Guide幫忙大家升級。問題在于Migration Guide并沒有詳盡的列出所有變動,本文以SQL模塊為主,扒一扒Spark升級2.x過程中可能會踩到的坑。
計算準確性
那些升級后,讓你感到心中有千萬只草泥馬奔騰而過的問題
SELECT '0.1' = 0
返回的是true!Spark 2.2中,0.1會被轉換為int,如果你的數據類型全部是文本類型,做數值計算時,結果極有可能不正確。之前的版本中0.1會被轉換為double類型絕大多數場景下這樣的處理是正確的。目前為止,社區還沒有很好的處理這個問題,針對這個問題,我給社區提交過一個PR,想要自己解決這個問題的同學,可以手動合并下:https://github.com/apache/spark/pull/18986- 過于復雜的SQL語句執行可能會出現64KB字節碼編譯限制的問題,這算是個老問題了,Spark自從上了Tungsten基本上一直存在這個問題,也算是受到了JVM的限制,遇到此類問題,建議大家找找PR:https://github.com/apache/spark/search?utf8=%E2%9C%93&q=64KB&type=Issues
- 數據計算精度有問題,
SELECT 1 > 0.0001
會報錯,這個問題已在2.1.2及2.2.0中修復:https://issues.apache.org/jira/browse/SPARK-20211 - 2.1.0版本中
INNER JOIN
涉及到常量計算結果不正確,后續版本已修復:https://issues.apache.org/jira/browse/SPARK-19766 - 2.1.0中,執行
GROUPING SET(col)
,如果col列數據為null,會報空指針異常,后續版本已修復:https://issues.apache.org/jira/browse/SPARK-19509 - 2.1.0中,嵌套的CASE WHEN語句執行有可能出錯,后續版本已修復:https://issues.apache.org/jira/browse/SPARK-19472
行為變化
那些不算太致命,改改代碼或配置就可以兼容的問題。
- Spark 2.2的UDAF實現有所變動,如果你的Hive UDAF沒有嚴格按照標準實現,有可能會計算報錯或數據不正確,建議將邏輯遷移到Spark AF,同時也能獲得更好的性能
- Spark 2.x限制了Hive表中
spark.sql.*
相關屬性的操作,明明存在的屬性,使用SHOW TBLPROPERTIES tb("spark.sql.sources.schema.numParts")
無法獲取到,同理也無法執行ALTER TABLE tb SET TBLPROPERTIES ('spark.sql.test' = 'test')
進行修改 - 無法修改外部表的屬性
ALTER TABLE tb SET TBLPROPERTIES ('test' = 'test')
這里假設tb是EXTERNAL類型的表 - DROP VIEW IF EXISTS tb,如果這里的tb是個TABLE而非VIEW,執行會報錯
AnalysisException: Cannot drop a table with DROP VIEW
,在2.x以下不會報錯,由于我們指定了IF EXISTS關鍵字,這里的報錯顯然不合理,需要做異常處理。 - 如果你訪問的表不存在,異常信息在Spark2.x里由之前的
Table not found
變成了Table or view not found
,如果你的代碼里依賴這個異常信息,就需要注意調整了。 - EXPLAIN語句的返回格式變掉了,在1.6里是多行文本,2.x中是一行,而且內容格式也有稍微的變化,相比Spark1.6,少了Tungsten關鍵字;EXPLAIN中顯示的HDFS路徑過長的話,在Spark 2.x中會被省略為...
- 2.x中默認不支持笛卡爾積操作,需要通過參數
spark.sql.crossJoin.enabled
開啟 - OLAP分析中常用的
GROUPING__ID
函數在2.x變成了GROUPING_ID()
- 如果你有一個基于Hive的UDF名為abc,有3個參數,然后又基于Spark的UDF實現了一個2個參數的abc,在2.x中,2個參數的abc會覆蓋掉Hive中3個參數的abc函數,1.6則不會有這個問題
- 執行類似
SELECT 1 FROM tb GROUP BY 1
的語句會報錯,需要單獨設置spark.sql.groupByOrdinal false
類似的參數還有spark.sql.orderByOrdinal false
- CREATE DATABASE默認路徑發生了變化,不在從hive-site.xml讀取
hive.metastore.warehouse.dir
,需要通過Spark的spark.sql.warehouse.dir
配置指定數據庫的默認存儲路徑。 - CAST一個不存在的日期返回null,如:year('2015-03-40'),在1.6中返回2015
- Spark 2.x不允許在VIEW中使用臨時函數(temp function)https://issues.apache.org/jira/browse/SPARK-18209
- Spark 2.1以后,窗口函數ROW_NUMBER()必須要在OVER內添加ORDER BY,以前的
ROW_NUMBER() OVER()
執行會報錯 - Spark 2.1以后,
SIZE(null)
返回-1,之前的版本返回null - Parquet文件的默認壓縮算法由gzip變成了snappy,據官方說法是snappy有更好的查詢性能,大家需要自己驗證性能的變化
- DESC FORMATTED tb返回的內容有所變化,1.6的格式和Hive比較貼近,2.x中分兩列顯示
- 異常信息的變化,未定義的函數,Spark 2.x:
org.apache.spark.sql.AnalysisException: Undefined function: 'xxx’.
, Spark 1.6:AnalysisException: undefined function xxx
,參數格式錯誤:Spark 2.x:Invalid number of arguments
, Spark 1.6:No handler for Hive udf class org.apache.hadoop.hive.ql.udf.generic.GenericUDAFXXX because: Exactly one argument is expected..
- Spark Standalone的WebUI中已經沒有這個API了:
/api/v1/applications
:https://issues.apache.org/jira/browse/SPARK-12299,https://issues.apache.org/jira/browse/SPARK-18683
版本回退
那些升級到2.x后,發現有問題回退后,讓你欲哭無淚的問題。
- Spark 2.0開始,SQL創建的分區表兼容Hive了,Spark會將分區信息保存到HiveMetastore中,也就是我們可以通過SHOW PARTITIONS查詢分區,Hive也能正常查詢這些分區表了。如果將Spark切換到低版本,在更新分區表,HiveMetastore中的分區信息并不會更新,需要執行
MSCK REPAIR TABLE
進行修復,否則再次升級會出現缺數據的現象。 - Spark 2.0 ~ 2.1創建的VIEW并不會把創建VIEW的原始SQL更新到HiveMetastore,而是解析后的SQL,如果這個SQL包含復雜的子查詢,那么切換到1.6后,就有可能無法使用這個VIEW表了(1.6對SQL的支持不如2.x)
其他
從2.2.0開始,Spark不在支持Hadoop 2.5及更早的版本,同時也不支持Java 7 了,所以,如果你用的版本比較老,還是盡快升級的比較好。
2.x中對于ThriftServer或JobServer這樣的長時間運行的服務,穩定性不如1.6,如果您的計算業務復雜、SQL計算任務繁多、頻繁的更新數據、處理數據量較大,穩定性的問題更加凸顯。穩定性問題主要集中在內存方面,Executor經常出現堆外內存嚴重超出、OOM導致進程異常退出等問題。Executor進程OOM異常退出后相關的block-mgr目錄(也就是SPARK_LOCAL_DIRS)并不會被清理,這就導致Spark Application長時間運行很容易出現磁盤被寫滿的情況。
總結
Spark 2.x中為了性能,SQL模塊的改動相當大,這也導致Bug變多,穩定性變差。當然,隨著Spark的不斷改進迭代,這些問題也在逐步緩解。
對于一個計算服務,相比性能,數據計算的正確性及穩定性更加重要。建議尚未升級到2.x的同學,最好使用最新的Spark版本做升級;升級前,務必結合自己的業務場景做好充分的測試,避免踩坑。
本文同步更新到微信公眾號,歡迎掃碼關注。
文章列表