標籤:
本文原文出處: http://blog.csdn.net/bluishglc/article/details/50748937 嚴禁任何形式的轉載,否則將委託CSDN官方維護權益!
問題描述
如果你在Spark SQL上試圖調用在HIVE註冊的自訂函數(UDF)時,你可能會遇到這樣的錯誤:
Spark SQL: Error in query: undefined function xxxxxx
這個問題發生在Spark 1.5.0, 1.5.1和1.5.2版本上,對此Spark官方有一個專門的bug report: https://issues.apache.org/jira/browse/SPARK-11191
簡單說, 引起這個bug的原因是Spark SQL在與HIVE的(主要是Hive的中繼資料)互動上,在UDF方面有問題,導致Spark SQL無法正確的得到UDF的資訊。針對這個問題最簡單的解決方案當然是升級Spark,但是可能受制於其他因素,我們無法升級,這時就需要從別的途徑來解決這個問題了。
解決方案
這裡提供一個參考的解決方案,這個方案的思路是:繞過HIVE,直接在Spark上註冊UDF。但這裡有一個地方需要斟酌的地方,那就是在哪裡和什麼樣的時機去註冊UDF。這裡有一個假定,即:所有的SQL語句是抽離到專門的SQL檔案中去,然後通過spark-sql -f /your/sql/file 的方式來執行的,通常我們認為這是更加規範的做法,而不是在scala或java代碼中去嵌入sql語句,那麼在這樣一個前提下,註冊UDF的入口應該是spark-sql這個指令碼的初始化環節中的某個地方,通過瀏覽Spark源碼,我們得知spark-sql的入口是
org.apache.spark.sql.hive.thriftserver.SparkSQLCLIDriver
而SparkSQLCLIDriver會通過
org.apache.spark.sql.hive.thriftserver.SparkSQLEnv#init
去初始化一個HiveContext, 這個HiveContext就是spark-sql啟動後建立的hiveContext執行個體,同時也是後續SQL執行時使用的hiveContext執行個體,因此在這個執行個體的初始化方法就是我們註冊我們的UDF的入口,我們可以在
hiveContext.setConf("spark.sql.hive.version", HiveContext.hiveExecutionVersion)
這一行之後添加註冊UDF的代碼:
hiveContext.udf.register("your_function_name",yourFunction _)
修改完成之後重新編譯,把編譯後的SparkSQLEnv的所有class檔案更新到各個節點的spark的jar包中就可以了。
Spark SQL: Error in query: undefined function錯誤的解決方案