1. 程式人生 > >重溫大資料---Hive進階

重溫大資料---Hive進階

這一塊的內容自我感覺算不上進階。除了一些看似需要死記硬背但實際上我並不會去背的東西,真沒啥好寫的。只能全當做筆記了。另外值得提一嘴的就是那個UDF,其實只要有那麼一點點Java基礎看起來就很簡單。不要因為程式設計兩個字就選擇性忽略了。單學習來講UDF程式設計還是很基礎的,在實際專案中視不同的需求可能會麻煩一點。但再難畢竟是Java老本行。

Hive關於庫的操作



一堆CDAUS:

create database db_hive_01 ;
create database if not exists db_hive_02 ;      //推薦這種寫法很標準
create database if not exists db_hive_03 location '/user/beifeng/hive/warehouse/db_hive_03.db' ;

show databases ;
show databases like 'db_hive*' ;

use db_hive ;

desc database db_hive_03 ;
desc database extended db_hive_03 ;           // 檢視拓展資訊
(資料庫刪除的同時資料庫的目錄也沒有了)
drop database db_hive_03 ;                          //有表存在就刪不了
drop database db_hive_03 cascade;            //級聯刪除,有表也能刪
drop database if exists db_hive_03 ;

這些是在是沒什麼好說的照搬筆記。

Hive關於表的操作



  • 建立表 ?

    1. 基礎的表建立格式
      create table IF NOT EXISTS default.xl_log_20181117(
      ip string COMMENT ‘remote ip address’//註釋 ,
      user string ,
      req_url string COMMENT ‘user request url’)
      COMMENT ‘BeiFeng Web Access Logs’
      ROW FORMAT DELIMITED FIELDS TERMINATED BY ’ ’ // 行分割
      STORED AS TEXTFILE ; //資料格式(預設如此可以不寫)
    2. //載入資料到表裡面
      load data local inpath ‘/opt/datas/xl-log.txt’ into table default.bf_log_20150913;
    3. //用查詢的資料建立一個新表
      create table IF NOT EXISTS default.xl_log_20150913_sa
      AS select ip,req_url from default.xl_log_20150913 ;
    4. // 拷貝表結構建立一個新的表,引出一個分表的概念
      create table IF NOT EXISTS default.xl_log_20150913_sa
      like default.xl_log_20150913 ;
  • 刪除表?

//建表
員工表
create table IF NOT EXISTS default.emp(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
部門表
create table IF NOT EXISTS default.dept(
deptno int,
dname string,
loc string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
//載入本地資料到表中
load data local inpath '/opt/datas/emp.txt' overwrite into table emp ;
load data local inpath '/opt/datas/dept.txt' overwrite into table dept ;

create table if not exists default.dept_cats
as select * from dept ;

//清除表的資料
truncate table dept_cats ;  

// 拷貝表結構建表
create table if not exists default.dept_like
like
default.dept ; 
//修改表名
alter table dept_like rename to dept_like_rename ;
//刪除表
drop table if exists dept_like_rename ;

Hive表的型別

1.管理表(manged_table)

  • 內部表也稱之為MANAGED_TABLE;
  • 預設儲存在/user/hive/warehouse下,也可以通過location指定;
  • 刪除表時,會刪除表資料以及元資料

2.託管表(external)

  • 外部表稱之為EXTERNAL_TABLE;
  • 在建立表時可以自己指定目錄位置(LOCATION);
  • 刪除表時,只會刪除元資料不會刪除表資料

使用外部表的場景:上述特點中可以看出在使用外部表的情況下刪除表的時候是不會刪除表中資料的。同時可以指定自己的目錄,通常必須指定。這樣可供多部門使用。

例子?:

create EXTERNAL table IF NOT EXISTS default.emp_ext2(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
location '/user/beifeng/hive/warehouse/emp_ext2';

分割槽表

分割槽表實際上就是對應一個HDFS檔案系統上的獨立的資料夾,該資料夾下是該分割槽所有的資料檔案。Hive中的分割槽就是分目錄,把一個大的資料集根據業務需要分割成更下的資料集。

使用場景:如對日誌進行分析,可以按照時間進行分割槽,提高分析效率。分析10G資料和分析1G資料你說誰快?

例子?:

create EXTERNAL table IF NOT EXISTS default.emp_partition(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int
)                  //二級分割槽.
partitioned by (month string,day string)     //不能與列名重複
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' ;

load data local inpath '/opt/datas/emp.txt' into table default.emp_partition partition (month='201509',day='13') ;
此時HDFS目錄結構為:
/user/hive/warehouse/emp_partition/month=201509/day=13

select * from emp_partition where month = '201509' and day = '13' ;

//統計幾天的資料可以使用union
select * from emp_partition where month = '201509' and day = '14' union
select * from emp_partition where month = '201509' and day = '15' union
select * from emp_partition where month = '201509' and day = '16' ;

例子?:

create table IF NOT EXISTS default.dept_part(
deptno int,
dname string,
loc string
)
partitioned by (day string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';

載入資料到表下面但是此時你沒有指定哪個分割槽,如果你去select你會發現查不出來資料。對此有一下兩種解決方案。

第一種方式
1.dfs -mkdir -p /user/hive/warehouse/dept_part/day=20150913 ;
  dfs -put /opt/datas/dept.txt /user/hive/warehouse/dept_part/day=20150913 ;	
2.hive (default)> msck repair table dept_part ;//修復表

第二種方式
1. dfs -mkdir -p /user/hive/warehouse/dept_part/day=20150914 ;
   dfs -put /opt/datas/dept.txt /user/hive/warehouse/dept_part/day=20150914 ;
2. alter table dept_part add partition(day='20150914');//(常用)

//檢視一個表的分割槽數
show partitions dept_part ;

Hive的資料遷移

載入資料

  • 原始檔案儲存的位置

    • 本地 local
    • 檔案系統hdfs
  • 對錶的資料是否覆蓋

    • 覆蓋 overwrite
    • 追加
  • 分割槽表載入,特殊性

      partition (partcol1=val1,...)
    

1)載入本地檔案到hive表

load data local inpath ‘/opt/datas/emp.txt’ into table default.emp ;
2)載入hdfs檔案到hive中

load data inpath ‘/user/beifeng/hive/datas/emp.txt’ into table default.emp ;

3)載入資料覆蓋表中已有的資料

load data inpath ‘/user/beifeng/hive/datas/emp.txt’ overwrite into table default.emp ;
4)建立表時通過insert載入

create table default.emp_ci like emp ;
insert into table default.emp_ci select * from default.emp ;

5)建立表的時候通過location指定載入

create EXTERNAL table IF NOT EXISTS default.emp_ext2(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
location '/user/beifeng/hive/warehouse/emp_ext2';

匯出資料

1. insert overwrite local directory '/opt/datas/hive_exp_emp'
   select * from default.emp ;

2. insert overwrite local directory '/opt/datas/hive_exp_emp2'
	ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' COLLECTION ITEMS TERMINATED BY '\n'
    select * from default.emp ;

3. bin/hive -e "select * from default.emp ;" > /opt/datas/exp_res.txt


4. insert overwrite directory '/user/beifeng/hive/hive_exp_emp'

   select * from default.emp ;
   
5. sqoop後面介紹

##Hive查詢

詳見官網

SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list]
[CLUSTER BY col_list
  | [DISTRIBUTE BY col_list] [SORT BY col_list]
]
[LIMIT number]

select * from emp ;
select t.empno, t.ename, t.deptno from emp t ;

select * from emp limit 5 ;
select t.empno, t.ename, t.deptno from emp t where  t.sal between 800 and 1500 ;

select t.empno, t.ename, t.deptno from emp t where comm is null ;

select count(*) cnt from emp ;
select max(sal) max_sal from emp ;
select sum(sal) from emp ;
select avg(sal) from emp ;

 group by分組 /having 條件
 
group by
* 每個部門的平均工資
select t.deptno, avg(t.sal) avg_sal from emp t group by t.deptno ;
* 每個部門中每個崗位的最高薪水
select t.deptno, t.job, max(t.sal) avg_sal from emp t group by t.deptno, job ;

having
	* where 是針對單條記錄進行篩選
	* having 是針對分組結果進行篩選
求每個部門的平均薪水大於2000的部門
select deptno, avg(sal) from emp group by deptno ;
select deptno, avg(sal) avg_sal from emp group by deptno having avg_sal > 2000;

join連線
	兩個表進行連線
	m  n
	m表中一條記錄和n表中的一條記錄組成一條記錄
等值jion
	join ... on
select e.empno, e.ename, d.deptno, d.dname from emp e join dept d on e.deptno = d.deptno ;

左連線
left join
select e.empno, e.ename, d.deptno, d.dname  from emp e left join dept d on e.deptno = d.deptno ;

右連線
right join
select e.empno, e.ename, e.deptno, d.dname  from emp e right join dept d on e.deptno = d.deptno ;


全連線(左+右)
full join
select e.empno, e.ename, e.deptno, d.dname  from emp e full join dept d on e.deptno = d.deptno ;

Hive 資料遷移新特性(類似與Get操作)

Export 
	匯出,將Hive表中的資料,匯出到外部
Import
	匯入,將外部資料匯入Hive表中

EXPORT TABLE default.emp TO  '/user/beifeng/hive/export/emp_exp'(自動建立) ;

export_target_path:	//指的是HDFS上路徑
//建立時使用import匯入資料
create table db_hive.emp like default.emp ;
import table db_hive.emp from '/user/beifeng/hive/export/emp_exp';

Hive 資料排序

order by
	對全域性資料的一個排序,僅僅只有個reduce
	select * from emp order by empno desc ;

sort by
	對每一個reduce內部資料進行排序的,全域性結果集來說不是排序

	set mapreduce.job.reduces= 3;
	select * from emp sort by empno asc ;
	insert overwrite local directory '/opt/datas/sortby-res' select * from emp sort by empno asc ;

 distribute by
	分割槽partition
	類似於MapReduce中分割槽partition,對資料進行分割槽,結合sort by進行使用
	insert overwrite local directory '/opt/datas/distby-res' select * from emp distribute by deptno sort by empno asc ;

    注意事項:
	distribute by 必須要在sort by前面。

 cluster by
	當distribute by和sort by 欄位相同時,可以使用cluster by ;
	insert overwrite local directory '/opt/datas/cluster-res' select * from emp cluster by empno ;

Hive UDF程式設計

UDF全稱User Definition Function,使用者自定義函式。使用極其簡單。

程式設計步驟:

  1. 匯入依賴

     <dependencies>
     	<!-- Hadoop Client -->
     	<dependency>
     		<groupId>org.apache.hadoop</groupId>
     		<artifactId>hadoop-client</artifactId>
     		<version>${hadoop.version}</version>
     	</dependency>
    
     	<!-- Hive Client -->
     	<dependency>
     		<groupId>org.apache.hive</groupId>
     		<artifactId>hive-jdbc</artifactId>
     		<version>${hive.version}</version>
     	</dependency>
     	<dependency>
     		<groupId>org.apache.hive</groupId>
     		<artifactId>hive-exec</artifactId>
     		<version>${hive.version}</version>
     	</dependency>
    
     	<!-- Junit 4.x -->
     	<dependency>
     		<groupId>junit</groupId>
     		<artifactId>junit</artifactId>
     		<version>4.10</version>
     		<scope>test</scope>
     	</dependency>
     </dependencies>
    
  2. 繼承org.apache.hadoop.hive.ql.UDF

  3. 需要實現evaluate函式;evaluate函式支援過載;
    public class LowerUDF extends UDF {

     public Text evaluate(Text str){
     	// validate 
     	if(null == str.toString()){
     		return null ;
     	}
     	// lower
     	return new Text (str.toString().toLowerCase())  ;
     }	
     public static void main(String[] args) {
     	System.out.println(new LowerUDF().evaluate(new Text("HIVE")));
     }
     }
    

    如何執行

    1. 方法一:
      add jar /opt/datas/hiveudf.jar ;//在hive執行下新增jar檔案
      create temporary function my_lower as “com.beifeng.senior.hive.udf.LowerUDF” ;//註冊臨時函式,指定用哪個類做處理
      select ename, my_lower(ename) lowername from emp limit 5 ;//呼叫函式
    2. 方法二:
      CREATE FUNCTION self_lower AS ‘com.beifeng.senior.hive.udf.LowerUDF’ USING JAR ‘hdfs://hadoop-senior.ibeifeng.com:8020/user/beifeng/hive/jars/hiveudf.jar’; //把本地jar傳上去,改檔案路徑需要提前建立
      select ename, self_lower(ename) lowername from emp limit 5 ;

總結

卒!