自定義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