4. Hive 查詢語法
4.1. SELECT
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list [HAVING condition]]
[CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list]
]
[LIMIT number]
- order by 會對輸入做全局排序,因此只有一個reducer,會導致當輸入規模較大時,需要較長的計算時間。
- sort by不是全局排序,其在數據進入reducer前完成排序。因此,如果用sort by進行排序,並且設置mapred.reduce.tasks>1,則sort by只保證每個reducer的輸出有序,不保證全局有序。
- distribute by(字段)根據指定的字段將數據分到不同的reducer,且分發算法是hash散列。
- cluster by(字段) 除了具有distribute by的功能外,還會對該字段進行排序.
因此,如果distribute 和sort字段是同一個時,此時,cluster by = distribute by + sort by
4.2. 查詢語法
select * from score;
select s_id ,c_id from score;
1)重命名一個列。
2)便於計算。
3)緊跟列名,也可以在列名和別名之間加入關鍵字‘AS’
select s_id as myid ,c_id from score;
4.3. 常用函數
- 求總行數(count)
select count(1) from score;
- 求分數的最大值(max)
select max(s_score) from score;
- 求分數的最小值(min)
select min(s_score) from score;
- 求分數的總和(sum)
select sum(s_score) from score;
- 求分數的平均值(avg)
select avg(s_score) from score;
4.4. LIMIT語句
典型的查詢會返回多行數據。LIMIT子句用於限制返回的行數。
select * from score limit 3;
4.5. WHERE語句
- 使用WHERE 子句,將不滿足條件的行過濾掉。
- WHERE 子句緊隨 FROM 子句。
- 案例實操
查詢出分數大於60的數據
select * from score where s_score > 60;
操作符 | 支持的數據類型 | 描述 |
---|---|---|
A=B | 基本數據類型 | 如果A等於B則返回TRUE,反之返回FALSE |
A<=>B | 基本數據類型 | 如果A和B都爲NULL,則返回TRUE,其他的和等號(=)操作符的結果一致,如果任一爲NULL則結果爲NULL |
A<>B, A!=B | 基本數據類型 | A或者B爲NULL則返回NULL;如果A不等於B,則返回TRUE,反之返回FALSE |
A<B | 基本數據類型 | A或者B爲NULL,則返回NULL;如果A小於B,則返回TRUE,反之返回FALSE |
A<=B | 基本數據類型 | A或者B爲NULL,則返回NULL;如果A小於等於B,則返回TRUE,反之返回FALSE |
A>B | 基本數據類型 | A或者B爲NULL,則返回NULL;如果A大於B,則返回TRUE,反之返回FALSE |
A>=B | 基本數據類型 | A或者B爲NULL,則返回NULL;如果A大於等於B,則返回TRUE,反之返回FALSE |
A [NOT] BETWEEN B AND C | 基本數據類型 | 如果A,B或者C任一爲NULL,則結果爲NULL。如果A的值大於等於B而且小於或等於C,則結果爲TRUE,反之爲FALSE。如果使用NOT關鍵字則可達到相反的效果。 |
A IS NULL | 所有數據類型 | 如果A等於NULL,則返回TRUE,反之返回FALSE |
A IS NOT NULL | 所有數據類型 | 如果A不等於NULL,則返回TRUE,反之返回FALSE |
IN(數值1, 數值2) | 所有數據類型 | 使用 IN運算顯示列表中的值 |
A [NOT] LIKE B | STRING 類型 | B是一個SQL下的簡單正則表達式,如果A與其匹配的話,則返回TRUE;反之返回FALSE。B的表達式說明如下:‘x%’表示A必須以字母‘x’開頭,‘%x’表示A必須以字母’x’結尾,而‘%x%’表示A包含有字母’x’,可以位於開頭,結尾或者字符串中間。如果使用NOT關鍵字則可達到相反的效果。 |
A RLIKE B, A REGEXP B | STRING | 類型 B是一個正則表達式,如果A與其匹配,則返回TRUE;反之返回FALSE。匹配使用的是JDK中的正則表達式接口實現的,因爲正則也依據其中的規則。例如,正則表達式必須和整個字符串A相匹配,而不是隻需與其字符串匹配。 |
- 查詢分數等於80的所有的數據
select * from score where s_score = 80;
- 查詢分數在80到100的所有數據
select * from score where s_score between 80 and 100;
- 查詢成績爲空的所有數據
select * from score where s_score is null;
- 查詢成績是80和90的數據
select * from score where s_score in(80,90);
4.6. LIKE 和 RLIKE
- 使用LIKE運算選擇類似的值
- 選擇條件可以包含字符或數字:
% 代表零個或多個字符(任意個字符)。
_ 代表一個字符。
-
RLIKE子句是Hive中這個功能的一個擴展,其可以通過Java的正則表達式這個更強大的語言來指定匹配條件。
-
案例實操
- 查找以8開頭的所有成績
select * from score where s_score like '8%';
- 查找第二個數值爲9的所有成績數據
select * from score where s_score like '_9%';
- 查找s_id中含1的數據
select * from score where s_id rlike '[1]'; # like '%1%'
4.7. 邏輯運算符
操作符 | 含義 |
---|---|
AND | 邏輯並 |
OR | 邏輯或 |
NOT | 邏輯否 |
- 查詢成績大於80,並且s_id是01的數據
select * from score where s_score >80 and s_id = '01';
- 查詢成績大於80,或者s_id 是01的數
select * from score where s_score > 80 or s_id = '01';
- 查詢s_id 不是 01和02的學生
select * from score where s_id not in ('01','02');
4.8. 分組
GROUP BY 語句
GROUP BY語句通常會和聚合函數一起使用,按照一個或者多個列隊結果進行分組,然後對每個組執行聚合操作。
案例實操:
- 計算每個學生的平均分數
select s_id ,avg(s_score) from score group by s_id;
- 計算每個學生最高成績
select s_id ,max(s_score) from score group by s_id;
HAVING 語句
-
having與where不同點
- where針對表中的列發揮作用,查詢數據;having針對查詢結果中的列發揮作用,篩選數據。
- where後面不能寫分組函數,而having後面可以使用分組函數。
- having只用於group by分組統計語句。
-
案例實操:
- 求每個學生的平均分數
select s_id ,avg(s_score) from score group by s_id;
- 求每個學生平均分數大於85的人
select s_id ,avg(s_score) avgscore from score group by s_id having avgscore > 85;
4.9. JOIN 語句
4.9.1. 等值 JOIN
Hive支持通常的SQL JOIN語句,但是隻支持等值連接,不支持非等值連接。
案例操作: 查詢分數對應的姓名
select s.s_id,s.s_score,stu.s_name,stu.s_birth from score s join student stu on s.s_id = stu.s_id;
4.9.2. 表的別名
-
好處
- 使用別名可以簡化查詢。
- 使用表名前綴可以提高執行效率。
-
案例實操
- 合併老師與課程表
select * from techer t join course c on t.t_id = c.t_id;
4.9.3. 內連接
內連接:只有進行連接的兩個表中都存在與連接條件相匹配的數據纔會被保留下來。
select * from techer t inner join course c on t.t_id = c.t_id;
4.9.4. 左外連接
左外連接:JOIN操作符左邊表中符合WHERE子句的所有記錄將會被返回。
查詢老師對應的課程
select * from techer t left join course c on t.t_id = c.t_id;
4.9.5. 右外連接
右外連接:JOIN操作符右邊表中符合WHERE子句的所有記錄將會被返回。
select * from teacher t right join course c on t.t_id = c.t_id;
4.9.6. 多表連接
注意:連接 n個表,至少需要n-1個連接條件。例如:連接三個表,至少需要兩個連接條件。
多表連接查詢,查詢老師對應的課程,以及對應的分數,對應的學生
select * from teacher t
left join course c
on t.t_id = c.t_id
left join score s
on s.c_id = c.c_id
left join student stu
on s.s_id = stu.s_id;
大多數情況下,Hive會對每對JOIN連接對象啓動一個MapReduce任務。本例中會首先啓動一個MapReduce job對錶techer和表course進行連接操作,然後會再啓動一個MapReduce job將第一個MapReduce job的輸出和表score;進行連接操作。
4.10. 排序
4.10.1. 全局排序
Order By:全局排序,一個reduce
-
使用 ORDER BY 子句排序
ASC(ascend): 升序(默認)
DESC(descend): 降序 -
ORDER BY 子句在SELECT語句的結尾。
-
案例實操
- 查詢學生的成績,並按照分數降序排列
SELECT * FROM student s LEFT JOIN score sco ON s.s_id = sco.s_id ORDER BY sco.s_score DESC;
- 查詢學生的成績,並按照分數升序排列
SELECT * FROM student s LEFT JOIN score sco ON s.s_id = sco.s_id ORDER BY sco.s_score asc;
4.10.2. 按照別名排序
按照分數的平均值排序
select s_id ,avg(s_score) avg from score group by s_id order by avg;
4.10.3. 多個列排序
按照學生id和平均成績進行排序
select s_id ,avg(s_score) avg from score group by s_id order by s_id,avg;
4.10.4. 每個MapReduce內部排序(Sort By)局部排序
Sort By:每個MapReduce內部進行排序,對全局結果集來說不是排序。
- 設置reduce個數
set mapreduce.job.reduces=3;
- 查看設置reduce個數
set mapreduce.job.reduces;
- 查詢成績按照成績降序排列
select * from score sort by s_score;
- 將查詢結果導入到文件中(按照成績降序排列)
insert overwrite local directory '/export/servers/hivedatas/sort' select * from score sort by s_score;
4.10.5. 分區排序(DISTRIBUTE BY)
Distribute By:類似MR中partition,進行分區,結合sort by使用。
注意,Hive要求DISTRIBUTE BY語句要寫在SORT BY語句之前。
對於distribute by進行測試,一定要分配多reduce進行處理,否則無法看到distribute by的效果。
案例實操:先按照學生id進行分區,再按照學生成績進行排序。
- 設置reduce的個數,將我們對應的s_id劃分到對應的reduce當中去
set mapreduce.job.reduces=7;
- 通過distribute by 進行數據的分區
insert overwrite local directory '/export/servers/hivedatas/sort' select * from score distribute by s_id sort by s_score;
4.10.6. CLUSTER BY
當distribute by和sort by字段相同時,可以使用cluster by方式。
cluster by除了具有distribute by的功能外還兼具sort by的功能。但是排序只能是倒序排序,不能指定排序規則爲ASC或者DESC。
以下兩種寫法等價
select * from score cluster by s_id;
select * from score distribute by s_id sort by s_id;
5.Hive Shell參數
5.1 Hive命令行
bin/hive [-hiveconf x=y]* [<-i filename>]* [<-f filename>|<-e query-string>] [-S]
1、 -i 從文件初始化HQL。
2、 -e從命令行執行指定的HQL
3、 -f 執行HQL腳本
4、 -v 輸出執行的HQL語句到控制檯
5、 -p connect to Hive Server on port number
6、 -hiveconf x=y Use this to set hive/hadoop configuration variables. 設置hive運行時候的參數配置
5.2 Hive參數配置方式
開發Hive應用時,不可避免地需要設定Hive的參數。設定Hive的參數可以調優HQL代碼的執行效率,或幫助定位問題。
對於一般參數,有以下三種設定方式:
- 配置文件
- 命令行參數
- 參數聲明
配置文件
:Hive的配置文件包括
-
用戶自定義配置文件:$HIVE_CONF_DIR/hive-site.xml
-
默認配置文件: $HIVE_CONF_DIR/hive-default.xml
用戶自定義配置會覆蓋默認配置。
另外,Hive也會讀入Hadoop的配置,因爲Hive是作爲Hadoop的客戶端啓動的,Hive的配置會覆蓋Hadoop的配置。
配置文件的設定對本機啓動的所有Hive進程都有效。
命令行參數:
啓動Hive(客戶端或Server方式)時,可以在命令行添加-hiveconf param=value來設定參數,例如:
bin/hive -hiveconf hive.root.logger=INFO,console
這一設定對本次啓動的Session(對於Server方式啓動,則是所有請求的Sessions)有效。
參數聲明
:可以在HQL中使用SET關鍵字設定參數,例如:
set mapred.reduce.tasks=100;
這一設定的作用域也是session級的。
上述三種設定方式的優先級依次遞增。即參數聲明覆蓋命令行參數,命令行參數覆蓋配置文件設定。注意某些系統級的參數,例如log4j相關的設定,必須用前兩種方式設定,因爲那些參數的讀取在Session建立以前已經完成了。
6. Hive 函數
6.1. 內置函數
內容較多,見《Hive官方文檔》
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF
-
查看系統自帶的函數
hive> show functions;
-
顯示自帶的函數的用法
hive> desc function upper;
-
詳細顯示自帶的函數的用法
hive> desc function extended upper;
4:常用內置函數
#字符串連接函數: concat
select concat('abc','def’,'gh');
#帶分隔符字符串連接函數: concat_ws
select concat_ws(',','abc','def','gh');
#cast類型轉換
select cast(1.5 as int);
#get_json_object(json 解析函數,用來處理json,必須是json格式)
select get_json_object('{"name":"jack","age":"20"}','$.name');
#URL解析函數
select parse_url('http://facebook.com/path1/p.php?k1=v1&k2=v2#Ref1', 'HOST');
#explode:把map集合中每個鍵值對或數組中的每個元素都單獨生成一行的形式
6.2. 自定義函數
####6.2.1 概述:
- Hive 自帶了一些函數,比如:max/min等,當Hive提供的內置函數無法滿足你的業務處理需要時,此時就可以考慮使用用戶自定義函數(UDF).
- 根據用戶自定義函數類別分爲以下三種:
- UDF(User-Defined-Function)
- 一進一出
- UDAF(User-Defined Aggregation Function)
- 聚集函數,多進一出
- 類似於:
count
/max
/min
- UDTF(User-Defined Table-Generating Functions)
- 一進多出
- 如
lateral
view
explore()
- UDF(User-Defined-Function)
- 編程步驟:
- 繼承org.apache.hadoop.hive.ql.UDF
- 需要實現evaluate函數;evaluate函數支持重載;
- 注意事項
- UDF必須要有返回類型,可以返回null,但是返回類型不能爲void;
- UDF中常用Text/LongWritable等類型,不推薦使用java類型;
####6.2.2 UDF 開發實例
Step 1 創建 Maven 工程
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.hive/hive-exec -->
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>2.7.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-common -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
Step 2 開發 Java 類集成 UDF
public class MyUDF extends UDF{
public Text evaluate(final Text str){
String tmp_str = str.toString();
if(str != null && !tmp_str.equals("")){
String str_ret = tmp_str.substring(0, 1).toUpperCase() + tmp_str.substring(1);
return new Text(str_ret);
}
return new Text("");
}
}
Step 3 項目打包,並上傳到hive的lib目錄下
Step 4 添加jar包
重命名我們的jar包名稱
cd /export/servers/apache-hive-2.7.5-bin/lib
mv original-day_10_hive_udf-1.0-SNAPSHOT.jar my_upper.jar
hive的客戶端添加我們的jar包
add jar /export/servers/apache-hive-2.7.5-bin/lib/my_upper.jar;
Step 5 設置函數與我們的自定義函數關聯
create temporary function my_upper as 'cn.cpz.udf.ItcastUDF';
Step 6 使用自定義函數
select my_upper('abc');