自定義UDF函式應用異常
版權宣告:本文為yunshuxueyuan原創文章。
如需轉載請標明出處: http://www.cnblogs.com/sxt-zkys/
QQ技術交流群:299142667
定義函式PlatformConvert:
實現傳入hive表中string型別欄位,通過查詢中間表,返回int型別主鍵id值
public class PlatformConvert extends UDF{ public IntWritable evaluate(Text s) throws Exception{ if(s==null){ return null; } PlatformDimension platformDimension = new PlatformDimension(s.toString()); IDimensionConverter convert = new DimensionConverterImpl(); int id=0; id = convert.getDimensionIdByValue(platformDimension); return new IntWritable(id); } }
UDF函式功能:例如引數為all,返回值為1;引數為website,返回值為2.
將定義好的UDF函式上傳到虛擬機器,並建立函式名稱為p_con的臨時函式
add jar /root/data/Fun.jar; create temporary function p_con as 'myudf.DateConvert';
建立stats_view_depth_tmp表
查詢表stats_view_depth_tmp,並將pl欄位值轉化成中間表對應的id
報錯內容大致意思為:不能執行自定義的函式
出現以上錯誤可能的情況
- jar不包含所有依賴項。可能不包括所有的依賴關係導致不能載入對應依賴的類資訊。
- JVM版本不同導致。如果使用jdk8進行編譯,並且叢集執行jdk7,那麼它也將失敗
- 蜂巢版本。有時候,蜂巢API變化很小,足夠不相容。可能不是這種情況,但是確保叢集中擁有相同版本的hadoop和hive來編譯UDF
- info呼叫後應該始終檢查是否為空parse()
具體錯誤資訊還需將進一步檢視日誌,只列出了關鍵資訊
2017-07-23 19:20:15,558 ERROR [main]: impl.DimensionConverterImpl (DimensionConverterImpl.java:getDimensionIdByValue(71)) - 運算元據庫出現異常
java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1094)
2017-07-23 19:20:15,561 ERROR [main]: CliDriver (SessionState.java:printError(960)) - Failed with exception java.io.IOException:org.apache.hadoop.hive.ql.metadata.HiveException: Unable to execute method public org.apache.hadoop.io.IntWritable UDF.PlatformConvert.evaluate(org.apache.hadoop.io.Text) throws java.lang.Exception on object UDF.PlatformConvert@7105159b of class UDF.PlatformConvert with arguments {website:org.apache.hadoop.io.Text} of size 1
java.io.IOException: org.apache.hadoop.hive.ql.metadata.HiveException: Unable to execute method public org.apache.hadoop.io.IntWritable UDF.PlatformConvert.evaluate(org.apache.hadoop.io.Text) throws java.lang.Exception on object UDF.PlatformConvert@7105159b of class UDF.PlatformConvert with arguments {website:org.apache.hadoop.io.Text} of size 1
at org.apache.hadoop.hive.ql.exec.FetchTask.fetch(FetchTask.java:154)
Caused by: org.apache.hadoop.hive.ql.metadata.HiveException: Unable to execute method public org.apache.hadoop.io.IntWritable UDF.PlatformConvert.evaluate(org.apache.hadoop.io.Text) throws java.lang.Exception on object UDF.PlatformConvert@7105159b of class UDF.PlatformConvert with arguments {website:org.apache.hadoop.io.Text} of size 1
at org.apache.hadoop.hive.ql.exec.FunctionRegistry.invoke(FunctionRegistry.java:981)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Caused by: java.io.IOException: java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)
Caused by: java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1094)
資訊點:提示資料庫異常
Access denied for user 'root'@'localhost' (using password: YES)
以上資訊大致推斷資料庫連線異常。
[錯誤解析]
主要原因: 執行自定義UDF函式的節點的和要查詢中間表所在資料庫不在同一個節點上而連線資料庫的URL為jdbc:mysql://127.0.0.1:3306/bigdata
解決辦法:1.修改中間表所在資料的許可權設定
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123' WITH GRANT OPTION;
給所有root使用者賦予所有許可權。這樣,即使不在同一節點上也可以相互操作對方的資料庫
2.修改連線資料庫的URL
jdbc:mysql://192.168.23.1:3306/bigdata
設定為要運算元據庫所對應的ip
3.重新打包上傳,並建立函式
重新執行
執行成功!
建立zj表,並插入資料
自定義函式platidutf,dateidudf同上面的自定義行數作用一致
通過自定義的函式查詢,並將對應的屬性值轉化成上文展示中間表的id值
如果將上一步操作查詢出來的資料插入到提前定義的表stats_view_depth1
操作語句
from zj insert into table stats_view_depth1 select platidudf(platform_dimension_id),dateidudf(data_dimension_id),kpi_dimension_id ,pv1,pv2,pv3,pv4,pv5_10,pv10_30,pv30_60, pv60_plus,created ;
執行後報錯如下:
執行後報錯如下:
後面提示資訊:No suitable sriver found for jdbc…,大致意思時沒有找到合適的驅動
報錯原因:yarn下沒找到資料庫的驅動包hadoop-2.6.5/share/hadoop/yarn
因為插入操作需要執行mapreduce作業,上文案例,通過自定義函式查詢操作,沒有執行mapreduce作業,對應的資料庫驅動是從hive目錄下載入,所以執行正常。
解決辦法:將hive目錄下的資料庫啟動拷貝到hadoop-2.6.5/share/hadoop/yarn目錄下
再次執行,一切正常。
Mysql許可權設定正確,但仍無法遠端訪問。通過telnet發現3306埠未開啟。
Mysql預設只繫結127.0.0.1,即:只有在本機才能訪問3306埠。
- 修改配置檔案中的bind-address或註釋
- 重啟MySQL。再通過遠端訪問就可以了,telnet可以發現埠也開啟了
通過改表法
mysql -u root -p123
mysql>use mysql;
update user set host = '%' where user = 'root';
mysql>select host, user from user;
通過授權法
1. 從任何主機都可以連線到mysql伺服器
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'mypassword' WITH GRANT OPTION;
2.指定連線資料庫的主機
GRANT ALL PRIVILEGES ON *.* TO ‘root’@'192.168.101.234' IDENTIFIED BY 'mypassword' WITH GRANT OPTION;
版權宣告:本文為yunshuxueyuan原創文章。
如需轉載請標明出處: http://www.cnblogs.com/sxt-zkys/
QQ技術交流群:299142667