1. 程式人生 > >Hive高階操作

Hive高階操作

目錄

1.Hive資料型別

1.1.原子資料型別

1.2.複雜資料型別

1.3.示例演示

1.3.1.array

1.3.2.map

1.3.3.struct

1.3.4.uniontype

2.檢視

3.Hive函式

3.1.Hive內建函式

3.2.Hive自定義函式UDF

3.2.1.一個簡單的UDF示例

3.2.2.Json資料解析UDF開發

3.2.3.Tranform實現

4.Hive特殊分隔符處理

4.1.使用RegexSerDe通過正則表示式來抽取欄位


1.Hive資料型別

1.1.原子資料型別

資料型別 長度 備註
Tinyint 1位元組的有符號整數 -128~127
SmallInt 1位元組的有符號整數 -32768~32767
Int 4位元組的有符號整數 -2147483648~2147483647
BigInt 8位元組的有符號整數 -9223372036854775808~9223372036854775807
Boolean 布林型別,true或者false true、false
Float 單精度浮點數  
Double 雙精度浮點數  
String 字串  
TimeStamp 整數 支援Unixtimestamp,可以達到納秒精度

1.Hive 支援日期型別(老版本不支援),在 Hive 裡日期一般都是用字串來表示的,而常用的日期格式轉化操作則是通過自定義函式進行操作,當然也可以直接指定為日期型別。
2.Hive 是用 Java 開發的,Hive 裡的基本資料型別和 java 的基本資料型別也是一一對應的,除了 String 型別。
3.有符號的整數型別:TINYINT、SMALLINT、INT 和 BIGINT 分別等價於 Java 的 Byte、Short、Int 和 Long 原子型別,它們分別為 1 位元組、2 位元組、4 位元組和 8 位元組有符號整數。
4.Hive 的浮點資料型別 FLOAT 和 DOUBLE,對應於 Java 的基本型別 Float 和 Double 型別。
5.Hive 的 BOOLEAN 型別相當於 Java 的基本資料型別 Boolean。
6.Hive 的 String 型別相當於資料庫的 Varchar 型別,該型別是一個可變的字串,不過它不能宣告其中最多能儲存多少個字元,理論上它可以儲存 2GB 的字元數。

1.2.複雜資料型別

複雜資料型別包括陣列(ARRAY)、對映(MAP)和結構體(STRUCT),具體如下所示:

說明

ARRAY:ARRAY 型別是由一系列相同資料型別的元素組成,這些元素可以通過下標來訪問。比如有一個 ARRAY 型別的變數 fruits,它是由['apple','orange','mango']組成,那麼我們可以通過 fruits[1]來訪問元素 orange,因為 ARRAY 型別的下標是從 0 開始的 。
MAP:MAP 包含 key->value 鍵值對,可以通過 key 來訪問元素。比如”userlist”是一個 map類 型 , 其 中 username 是 key , password 是 value ; 那 麼 我 們 可 以 通 過userlist['username']來得到這個使用者對應的 password。
STRUCT:STRUCT 可以包含不同資料型別的元素。這些元素可以通過”點語法”的方式來得到所需要的元素,比如 user 是一個 STRUCT 型別,那麼可以通過 user.address 得到這個使用者的地址。

示例

CREATE TABLE student(
name STRING,
favors ARRAY<STRING>,
scores MAP<STRING, FLOAT>,
 address STRUCT<province:STRING, city:STRING, detail:STRING, zip:INT>

 ROW FORMAT DELIMITED 
 FIELDS TERMINATED BY '\t' 
 COLLECTION ITEMS TERMINATED BY ';'
MAP KEYS TERMINATED BY ':' ;

說明:
1.欄位 name 是基本型別,favors 是陣列型別,可以儲存很多愛好,scores 是對映型別,可以儲存多個課程的成績,address 是結構型別,可以儲存住址資訊。
2.ROW FORMAT DELIMITED 是指明後面的關鍵詞是列和元素分隔符的
3.FIELDS TERMINATED BY 是欄位分隔符
4.COLLECTION ITEMS TERMINATED BY 是元素分隔符(Array 中的各元素、Struct 中的各元素、Map 中的 key-value 對之間)
5.MAP KEYS TERMINATED BY 是 Map 中 key 與 value 的分隔符
6.LINES TERMINATED BY 是行之間的分隔符
8.STORED AS TEXTFILE 指資料檔案上傳之後儲存的格式

總結:在關係型資料庫中,我們至少需要三張表來定義,包括學生基本表、愛好表、成績表;但在 Hive 中通過一張表就可以搞定了。也就是說,複合資料型別把多表關係通過一張表就可以實現了。

1.3.示例演示

1.3.1.array

建表語句
create table person1(name string,work_locations array<string>)
row format delimited fields terminated by '\t'
collection items terminated by ',';
資料
huangbo beijing,shanghai,tianjin,hangzhou
xuzheng changchu,chengdu,wuhan
wangbaoqiang dalian,shenyang,jilin
匯入資料
load data local inpath '/home/hadoop/person.txt' into table person1;
查詢語句
Select * from person1;
Select name from person1;
Select work_locations from person1;
Select work_locations[0] from person1;

1.3.2.map

建表語句
create table score(name string, scores map<string,int>)
row format delimited fields terminated by '\t'
collection items terminated by ','
map keys terminated by ':';
資料
huangbo yuwen:80,shuxue:89,yingyu:95
Stay hungry Stay foolish -- http://blog.csdn.net/zhongqi2513
xuzheng yuwen:70,shuxue:65,yingyu:81
wangbaoqiang yuwen:75,shuxue:100,yingyu:75
匯入資料
load data local inpath '/home/hadoop/score.txt' into table score;
查詢語句
Select * from score;
Select name from score;
Select scores from score;
Select s.scores['yuwen'] from score s;

1.3.3.struct

建表語句:
create table structtable(id int,course struct<name:string,score:int>)
row format delimited fields terminated by '\t'
collection items terminated by ',';
資料:
1 english,80
2 math,89
3 chinese,95
匯入資料:
load data local inpath '/ home/hadoop / structtable.txt' into table structtable;
查詢語句:
Select * from structtable;
Select id from structtable;
Select course from structtable;
Select t.course.name from structtable t;
Select t.course.score from structtable t;

1.3.4.uniontype

參考資料:http://yugouai.iteye.com/blog/18491

2.檢視

和關係型資料庫一樣,Hive 也提供了檢視的功能,不過請注意,Hive 的檢視和關係型資料庫的資料還是有很大的區別:
1.只有邏輯檢視,沒有物化檢視;
2.檢視只能查詢,不能 Load/Insert/Update/Delete 資料;
3.檢視在建立時候,只是儲存了一份元資料,當查詢檢視的時候,才開始執行檢視對應的那些子查詢
建立檢視
create view view_name as select * from carss;
create view carss_view as select * from carss limit 500;
檢視檢視
show tables; // 可以查看錶,也可以檢視檢視
desc view_name // 檢視某個具體檢視的資訊
desc carss_view
刪除檢視
drop view view_name
drop view if exists carss_view
使用檢視
create view sogou_view as select * from sogou_table where rank > 3 ;
select count(distinct uid) from sogou_view;

3.Hive函式

3.1.Hive內建函式

1.內容比較多,見《Hive官方文件》

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF

2.測試內建函式的快捷方式:

第一種方式:直接使用,例如:select concat('a','a') —> aa

第二種方式:

  • 建立一個 dual 表 create table dual(id string);
  • load 一個檔案(一行,一個空格)到 dual 表
  • select substr('huangbo',2,3) from dual;

3.檢視內建函式:
show functions;
顯示函式的詳細資訊:
desc function abs;
顯示函式的擴充套件資訊:
desc function extended concat;

4.內建函式列表

關係運算

1. 等值比較: =
2. 等值比較:<=>
3. 不等值比較: <>和!=
4. 小於比較: <
5. 小於等於比較: <=
6. 大於比較: >
7. 大於等於比較: >=
8. 區間比較
9. 空值判斷: IS NULL
10. 非空判斷: IS NOT NULL
10. LIKE 比較: LIKE
11. JAVA 的 LIKE 操作: RLIKE
12. REGEXP 操作: REGEXP

數學運算

1. 加法操作: +
2. 減法操作: –
3. 乘法操作: *
4. 除法操作: /
5. 取餘操作: %
6. 位與操作: &
7. 位或操作: |
8. 位異或操作: ^
9.位取反操作: ~

邏輯運算

1. 邏輯與操作: AND 、&&
2. 邏輯或操作: OR 、||
3. 邏輯非操作: NOT、!

複合型別建構函式

1. map 結構
2. struct 結構
3. named_struct 結構
4. array 結構
5. create_union

複合型別操作符

1. 獲取 array 中的元素
2. 獲取 map 中的元素
3. 獲取 struct 中的元素

數值計算函式

1. 取整函式: round
2. 指定精度取整函式: round
3. 向下取整函式: floor
4. 向上取整函式: ceil
5. 向上取整函式: ceiling
6. 取隨機數函式: rand
7. 自然指數函式: exp
8. 以 10 為底對數函式: log10
9. 以 2 為底對數函式: log2
10. 對數函式: log
11. 冪運算函式: pow
12. 冪運算函式: power
13. 開平方函式: sqrt
14. 二進位制函式: bin
15. 十六進位制函式: hex
16. 反轉十六進位制函式: unhex
17. 進位制轉換函式: conv
18. 絕對值函式: abs
19. 正取餘函式: pmod
20. 正弦函式: sin
21. 反正弦函式: asin
22. 餘弦函式: cos
23. 反餘弦函式: acos
24. positive 函式: positive
25. negative 函式: negative

集合操作函式

1. map 型別大小:size
2. array 型別大小:size
3. 判斷元素陣列是否包含元素:array_contains
4. 獲取 map 中所有 value 集合
5. 獲取 map 中所有 key 集合
6. 陣列排序

型別轉換函式

1. 二進位制轉換:binary
2. 基礎型別之間強制轉換:cast

日期函式

1. UNIX 時間戳轉日期函式: from_unixtime
2. 獲取當前 UNIX 時間戳函式: unix_timestamp
3. 日期轉 UNIX 時間戳函式: unix_timestamp
4. 指定格式日期轉 UNIX 時間戳函式: unix_timestamp
5. 日期時間轉日期函式: to_date
6. 日期轉年函式: year
7. 日期轉月函式: month
8. 日期轉天函式: day
9. 日期轉小時函式: hour
10. 日期轉分鐘函式: minute
11. 日期轉秒函式: second
12. 日期轉周函式: weekofyear
13. 日期比較函式: datediff
14. 日期增加函式: date_add
15. 日期減少函式: date_sub

條件函式

1. If 函式: if
2. 非空查詢函式: COALESCE
3. 條件判斷函式:CASE

字串函式

1. 字元 ascii 碼函式:ascii
2. base64 字串
3. 字串連線函式:concat
4. 帶分隔符字串連線函式:concat_ws
5. 陣列轉換成字串的函式:concat_ws
6. 小數位格式化成字串函式:format_number
7. 字串擷取函式:substr,substring
8. 字串擷取函式:substr,substring
9. 字串查詢函式:instr
10. 字串長度函式:length
11. 字串查詢函式:locate
12. 字串格式化函式:printf
13. 字串轉換成 map 函式:str_to_map
14. base64 解碼函式:unbase64(string str)
15. 字串轉大寫函式:upper,ucase
16. 字串轉小寫函式:lower,lcase
17. 去空格函式:trim
18. 左邊去空格函式:ltrim
19. 右邊去空格函式:rtrim
20. 正則表示式替換函式:regexp_replace
21. 正則表示式解析函式:regexp_extract
22. URL 解析函式:parse_url
23. json 解析函式:get_json_object
24. 空格字串函式:space
25. 重複字串函式:repeat
26. 左補足函式:lpad
Stay hungry Stay foolish -- http://blog.csdn.net/zhongqi2513
27. 右補足函式:rpad
28. 分割字串函式: split
29. 集合查詢函式: find_in_set
30. 分詞函式:sentences
31. 分詞後統計一起出現頻次最高的 TOP-K
32. 分詞後統計與指定單詞一起出現頻次最高的 TOP-K

混合函式

1. 呼叫 Java 函式:java_method
2. 呼叫 Java 函式:reflect
3. 字串的 hash 值:hash

XPathXML函式

1. xpath
2. xpath_string
3. xpath_boolean
4. xpath_short, xpath_int, xpath_long
5. xpath_float, xpath_double, xpath_number

彙總統計函式(UDAF)

1. 個數統計函式: count
2. 總和統計函式: sum
3. 平均值統計函式: avg
4. 最小值統計函式: min
5. 最大值統計函式: max
6. 非空集合總體變數函式: var_pop
7. 非空集合樣本變數函式: var_samp
8. 總體標準偏離函式: stddev_pop
9. 樣本標準偏離函式: stddev_samp
10.中位數函式: percentile
11. 中位數函式: percentile
12. 近似中位數函式: percentile_approx
13. 近似中位數函式: percentile_approx
14. 直方圖: histogram_numeric
15. 集合去重數:collect_set
16. 集合不去重函式:collect_list

表格生成函式Table-Generating Functions(UDTF)

1.陣列拆分成多行:explode(array)
2.Map 拆分成多行:explode(map)

3.2.Hive自定義函式UDF

當 Hive 提供的內建函式無法滿足業務處理需要時,此時就可以考慮使用使用者自定義函式
UDF(user-defined function)作用於單個數據行,產生一個數據行作為輸出。(數學函式,字串函式)
UDAF(使用者定義聚集函式 User- Defined Aggregation Funcation):接收多個輸入資料行,併產生一個輸出資料行。(count,max)
UDTF(表格生成函式 User-Defined Table Functions):接收一行輸入,輸出多行(explode)

3.2.1.一個簡單的UDF示例

1.先開發一個簡單的 java 類,繼承 org.apache.hadoop.hive.ql.exec.UDF,過載 evaluate 方法
Package com.ghgj.hive.udf
import java.util.HashMap;
import org.apache.hadoop.hive.ql.exec.UDF;
public class ToLowerCase extends UDF {
// 必須是 public,並且 evaluate 方法可以過載
public String evaluate(String field) {
String result = field.toLowerCase();
return result;
}
}
2.打成 jar 包上傳到伺服器
3.將 jar 包新增到 hive 的 classpath
hive>add JAR /home/hadoop/hivejar/udf.jar;
檢視加入的 jar/jars 的命令:
hive> list jar;
4.建立臨時函式與開發好的 class 關聯起來
hive>create temporary function tolowercase as 'com.ghgj.hive.udf.ToLowerCase';
5.至此,便可以在 hql 在使用自定義的函式
select tolowercase(name),age from student;

3.2.2.Json資料解析UDF開發

現有原始 json 資料(rating.json)如下,
{"movie":"1193","rate":"5","timeStamp":"978300760","uid":"1"}
{"movie":"661","rate":"3","timeStamp":"978302109","uid":"1"}
{"movie":"914","rate":"3","timeStamp":"978301968","uid":"1"}
{"movie":"3408","rate":"4","timeStamp":"978300275","uid":"1"}
Stay hungry Stay foolish -- http://blog.csdn.net/zhongqi2513
{"movie":"2355","rate":"5","timeStamp":"978824291","uid":"1"}
{"movie":"1197","rate":"3","timeStamp":"978302268","uid":"1"}
{"movie":"1287","rate":"5","timeStamp":"978302039","uid":"1"}
{"movie":"2804","rate":"5","timeStamp":"978300719","uid":"1"}
{"movie":"594","rate":"4","timeStamp":"978302268","uid":"1"}
現在需要將資料匯入到 hive 倉庫中,並且最終要得到這麼一個結果:

movie rate timeStamp uid
1193 5 978300760 1

該怎麼做???(提示:可用內建 get_json_object 或者自定義函式完成)

3.2.3.Tranform實現

Hive 的 TRANSFORM 關鍵字提供了在 SQL 中呼叫自寫指令碼的功能。適合實現 Hive 中沒有的功能又不想寫 UDF 的情況。

具體以一個例項講解。
Json 資料:{"movie":"1193","rate":"5","timeStamp":"978300760","uid":"1"}
需求:把 timestamp 的值轉換成日期編號

1.先載入 rating.json 檔案到 hive 的一個原始表 rate_json
create table rate_json(line string) row format delimited;
load data local inpath '/home/hadoop/rating.json' into table rate_json;

2.建立 rate 這張表用來儲存解析 json 出來的欄位:
create table rate(movie int, rate int, unixtime int, userid int) row format delimited fields terminated by '\t';
解析 json,得到結果之後存入 rate 表:
insert into table rate select 
get_json_object(line,'$.movie') as moive,
get_json_object(line,'$.rate') as rate,
get_json_object(line,'$.timeStamp') as unixtime,
get_json_object(line,'$.uid') as userid 
from rate_json;

3.使用 transform+python 的方式去轉換 unixtime 為 weekday

先編輯一個 python 指令碼檔案

########python######程式碼
## vi weekday_mapper.py
#!/bin/python
import sys
import datetime
for line in sys.stdin:
 line = line.strip()
 movie,rate,unixtime,userid = line.split('\t')
 weekday = datetime.datetime.fromtimestamp(float(unixtime)).isoweekday()
 print '\t'.join([movie, rate, str(weekday),userid])

儲存檔案
然後,將檔案加入 hive 的 classpath:
hive>add file /home/hadoop/weekday_mapper.py;
hive> insert into table lastjsontable select transform(movie,rate,unixtime,userid)
using 'python weekday_mapper.py' as(movie,rate,weekday,userid) from rate;

// 建立最後的用來儲存呼叫 python 指令碼解析出來的資料的表:lastjsontable
create table lastjsontable(movie int, rate int, weekday int, userid int) row format delimited fields terminated by '\t';

最後查詢看資料是否正確:
select distinct(weekday) from lastjsontable;

4.Hive特殊分隔符處理

補充:hive 讀取資料的機制:
1.首先用 InputFormat<預設是:org.apache.hadoop.mapred.TextInputFormat >的一個具體實現類讀入檔案資料,返回一條一條的記錄(可以是行,或者是你邏輯中的“行”)。
2.然後利用 SerDe<預設:org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe>的一個具體實現類,對上面返回的一條一條的記錄進行欄位切割。

Hive 對檔案中欄位的分隔符預設情況下只支援單位元組分隔符,如果資料檔案中的分隔符是多字元的,如下所示:
01||huangbo
02||xuzheng
03||wangbaoqiang

4.1.使用RegexSerDe通過正則表示式來抽取欄位

create table t_bi_reg(id string,name string)
row format serde 'org.apache.hadoop.hive.serde2.RegexSerDe'
with serdeproperties('input.regex'='(.*)\\|\\|(.*)','output.format.string'='%1$s %2$s')
stored as textfile;

hive>load data local inpath '/home/hadoop /hivedata/bi.dat' into table t_bi_reg;
hive>select * from t_bi_reg;