1. 程式人生 > >hive的(ql)hql使用和基於UDF的用法;以及java對hive的遠端訪問

hive的(ql)hql使用和基於UDF的用法;以及java對hive的遠端訪問

1>hive下建立表並匯入資料

  (資料可以是本地的,也可以是hdfs上的)

  

>建立本地檔案
[[email protected] /]# vi student
  1,xiaoming
  2,xiaohong
  3,xiaogang
  4,tom
  5,tim
>hive下建立表;desc table;檢視自己建立的表結構
  create table t1(id int,name String) row format delimited fields terminated by ',';
>將本地檔案匯入表中   load data local inpath
'/student' into table t1;
>每次上傳同一個資料到同一個表中,會自動拷貝一份,所以可以使用overwrite
  load data local inpath '/student'  overwrite into table t1;
>查看錶中資料:   select * from t1;
>統計表裡面一共有多少條記錄;
  select count(id) from t1;     #執行的時候執行在mapredurce上
>刪除表
  drop table t1;

 

2>內部表與外部表

 外部表和 內部表 在元資料的組織上是相同的,而實際資料的儲存則有較大的差異 內部表 的建立過程和資料載入過程(這兩個過程可以在同一個語句中完成),在載入 資料的過程中,實際資料會被移動到資料倉庫目錄中;之後對資料對訪問將會直接在資料倉 庫目錄中完成。刪除表時,表中的資料和元資料將會被同時刪除

    外部表 只有一個過程,載入資料和建立表同時完成,並不會移動到資料倉庫目錄中, 只是與外部資料建立一個連結。當刪除一個 外部表 時,僅刪除該連結

>建立內部表步驟如上,相比缺少了external關鍵字的使用
>建立外部表
create external table t2 (id int,name String) row format delimited fields
terminated by ',';

3>建立分割槽表

  把不同型別的資料放到不同的目錄下;

1>建立分割槽表
  create table t3 (id int
,name String ) partitioned by (subid int ) row   format delimited fields terminated by ',';
2>向表中插入資料
  load data local inpath '/student' into table t3 partition(subid=1) ;
  load data local inpath '/student2' overwrite into table t3 partition(subid=2) ;
3>查詢分割槽:
  hive> show partitions t3;
4>查詢分割槽的某個檔案
  select * from t3 where subid=2;
效果如圖:t3這個目錄中含有兩個不同的資料表,查詢的時候可以提高效率

 

4>基於UDF對錶中資料的查詢操作:

寫一個類繼承與hive的UDF類,寫一個方法,必須是evaluate,支援過載
package com.zhiyou.han.udf;

import java.util.HashMap;
import java.util.Map;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;

public class MyUDF extends UDF{

        private static Map<String, String> map= new HashMap<String, String>();
        
        
        static {
            map.put("xiaoming", "小明");
       map.put("xiaohong", "小紅"); }
public static Text evaluate(Text name) { String getName = name.toString(); String chainName = map.get(getName); if(chainName==null) { chainName = "null"; } return new Text(chainName); } }

>將這個類到處jar包上傳liunx下  /注意jar包的地址

  hive> add jar /U.jar;

>命名臨時函式名:

  hive> create temporary function U as 'com.zhiyou100.udf.MyUDF';

>平常查出結果是這樣的

  hive> select id ,name from t1;
    OK
    1 xiaoming
    2 xiaohong
    3 xiaogang

>使用UDF查詢後

  hive> select id ,U(name) from t1;
    OK
    1 小明
    2 小紅
    3 無名

>銷燬臨時的函式

  hive> drop temporary function U;

>刪除jar包

  hive> delete jar /U.jar

5>使用java遠端訪問liunx下的hive

1>與jdbc的執行流程是一樣的
  jdbc的執行流程:
    1.載入驅動
    2.建立連線
    3.準備sql
    4.執行sql
    5.處理結果
    6.釋放資
2>liunx下啟動hive的遠端服務:
>啟動遠端服務:
  #hive --service hiveserver     //版本1的
  #hive hiveserver2          //版本2的

>啟動過程中在liunx下使用命令連線看是否能成功連線上
    beeline -u jdbc:hive2://ip:10000/資料庫名 IP 可以寫自己的主機名或是自己的主機的IP地址
>報錯如下
   >出現root is not allowed tp (state=08S01,code=0)
    需要在hadoop配置檔案下core-site.xml檔案中加入如下程式碼: 然後停止(stop-all.sh)hadoop,在啟動(start-all.sh)hadoop,其中不需要預格式化,然後重新啟動hive(直接輸入hive)  
  <property>    
        <name>hadoop.proxyuser.root.hosts</name>    
        <value>*</value>
   </property>
   <property>    
        <name>hadoop.proxyuser.root.groups</name>    
        <value>*</value>
   </property>
  >如果報錯:  inode="tmp/hive"  root:supergroup:drwx----  是因為許可權的問題
   
執行一下該命令
    hdfs dfs -chmod -R 777  /tmp/

3>執行完上述步驟,保證可以遠端訪問: 

然後寫java程式碼如下:
package com.zhiyou.han.hiveApi;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import org.apache.hadoop.io.Text;

import com.zhiyou.han.udf.MyUDF;

public class HiveApi {

    // 要求必須liunx下hive開啟遠端服務,和訪問本地的的mysql資料庫一個原理
    
    public static void main(String[] args) throws Exception {
        // 1.載入驅動

        Class.forName("org.apache.hive.jdbc.HiveDriver");

        // 2.建立連線,輸入自己的IP,且埠號為  1000

        String url = "jdbc:hive2://192.168.188.130:10000/default";

        String user = "root";

        String password = "root";

        Connection conn = DriverManager.getConnection(url, user, password);

        // 3.準備sql語句    

        String sql = "select id,name from t2";

        PreparedStatement ps = conn.prepareStatement(sql);

        // 4.執行sql語句

        ResultSet rs = ps.executeQuery();

        // 5.處理結果
        while (rs.next()) {
       //這部分可以自己發揮寫,只要資料對照資料庫中的名字就行 System.
out.println(rs.getInt("id") + "\t" + MyUDF.evaluate(new Text(rs.getString("name")))); } // 6.釋放資源 rs.close(); ps.close(); conn.close(); } }