歡迎訪問我的GitHub
https://github.com/zq2599/blog_demos
內容:所有原創文章分類匯總及配套源碼,涉及Java、Docker、Kubernetes、DevOPS等;
《hive學習筆記》系列導航
本篇概覽
- 本文是《hive學習筆記》系列的第六篇,前面的文章咱們對數據類型、表結構有了基本了解,接下來對常用的查詢語句做一次集中式的學習;
- HiveQL與SQL類似, 在語法上與大部分SQL兼容, 但是並非完全兼容,例如更新、事務等都不支持,子查詢和join操作也有限, 這和底層依賴Hadoop有關;
准備數據
- 本次實戰要准備兩個表:學生表和住址表,字段都很簡單,如下圖所示,學生表有個住址ID字段,是住址表里的記錄的唯一ID:
2. 先創建住址表:
create table address (addressid int, province string, city string)
row format delimited
fields terminated by ',';
- 創建address.txt文件,內容如下:
1,guangdong,guangzhou
2,guangdong,shenzhen
3,shanxi,xian
4,shanxi,hanzhong
6,jiangshu,nanjing
- 加載數據到address表:
load data
local inpath '/home/hadoop/temp/202010/25/address.txt'
into table address;
- 創建學生表,其addressid字段關聯了address表的addressid字段:
create table student (name string, age int, addressid int)
row format delimited
fields terminated by ',';
- 創建student.txt文件,內容如下:
tom,11,1
jerry,12,2
mike,13,3
john,14,4
mary,15,5
- 加載數據到student表:
load data
local inpath '/home/hadoop/temp/202010/25/student.txt'
into table student;
- 至此,本次操作所需數據已准備完畢,如下所示:
hive> select * from address;
OK
1 guangdong guangzhou
2 guangdong shenzhen
3 shanxi xian
4 shanxi hanzhong
6 jiangshu nanjing
Time taken: 0.043 seconds, Fetched: 5 row(s)
hive> select * from student;
OK
tom 11 1
jerry 12 2
mike 13 3
john 14 4
mary 15 5
Time taken: 0.068 seconds, Fetched: 5 row(s)
- 開始體驗HiveQL
select和where
最普通的帶條件查詢:
hive> select * from address where city like '%a%';
OK
1 guangdong guangzhou
3 shanxi xian
4 shanxi hanzhong
6 jiangshu nanjing
Time taken: 0.128 seconds, Fetched: 4 row(s)
group by
- 按province字段分組:
select province, count(*) from address group by province;
該查詢會觸發MR計算,結果如下:
...
Total MapReduce CPU Time Spent: 1 seconds 910 msec
OK
guangdong 2
jiangshu 1
shanxi 2
Time taken: 17.847 seconds, Fetched: 3 row(s)
- 試試嵌套查詢,內部是查出city字段帶有a字母的記錄,然后將這些記錄按照province字段分組:
select t.province, count(*) from (
select * from address where city like '%a%'
) t
group by t.province;
結果如下:
Total MapReduce CPU Time Spent: 1 seconds 760 msec
OK
guangdong 1
jiangshu 1
shanxi 2
Time taken: 18.036 seconds, Fetched: 3 row(s)
having
- 前面的嵌套查詢,結果有兩個省:guangdong和shanxi,如果再加個條件:只顯示城市數量大於1的省,首先想到的是再加一層嵌套:
select t1.* from (
select t.province, count(*) as cnt from (
select * from address where city like '%a%'
) t
group by t.province) t1
where t1.cnt>1;
結果如下,可見只有shanxi被顯示了:
Total MapReduce CPU Time Spent: 2 seconds 250 msec
OK
shanxi 2
Time taken: 20.067 seconds, Fetched: 1 row(s)
- 對於上述SQL,可以用having語法進行分組篩選,得到同樣數據:
select t.province, count(*) as cnt from (
select * from address where city like '%a%'
) t
group by t.province having cnt>1;
order by
- 對分組結果做排序:
select t.province, count(*) as cnt from (
select * from address where city like '%a%'
) t
group by t.province order by cnt;
會觸發MR,結果如下:
Total MapReduce CPU Time Spent: 3 seconds 50 msec
OK
jiangshu 1
guangdong 1
shanxi 2
Time taken: 40.315 seconds, Fetched: 3 row(s)
- order by對於的實現,是在最后通過一個reducer進行全部排序,該過程可能耗時較長,針對這種情況,hive提供了sort by,功能與order by一樣,但是會在每個reducer中進行排序,這樣最終做排序的時候效率就會提升;
- 要注意的是:sort by解決的問題是最終結果排序的效率,因此數據量不大時,排序不是瓶頸,此時使用sort by也不會加快整體速度;
內連接(inner join)
- 內連接用join簡寫,與連接標准匹配的數據在兩張表中都存在,才會保留:
select
s.name, s.age,
a.province, a.city
from
student s
inner join
address a
on
s.addressid=a.addressid;
結果如下:
Total MapReduce CPU Time Spent: 1 seconds 20 msec
OK
tom 11 guangdong guangzhou
jerry 12 guangdong shenzhen
mike 13 shanxi xian
john 14 shanxi hanzhong
Time taken: 17.294 seconds, Fetched: 4 row(s)
自然連接(natural join)
- 自然連接是在兩張表中尋找數據類型和列明都相同的字段,並自動連接起來:
select name, age, province, city from student natural join address;
結果如下,可見不會根據student表的addressid字段值去address查找記錄,而是將addrerss的記錄全部連接一次:
Total MapReduce CPU Time Spent: 940 msec
OK
tom 11 guangdong guangzhou
jerry 12 guangdong guangzhou
mike 13 guangdong guangzhou
john 14 guangdong guangzhou
mary 15 guangdong guangzhou
tom 11 guangdong shenzhen
jerry 12 guangdong shenzhen
mike 13 guangdong shenzhen
john 14 guangdong shenzhen
mary 15 guangdong shenzhen
tom 11 shanxi xian
jerry 12 shanxi xian
mike 13 shanxi xian
john 14 shanxi xian
mary 15 shanxi xian
tom 11 shanxi hanzhong
jerry 12 shanxi hanzhong
mike 13 shanxi hanzhong
john 14 shanxi hanzhong
mary 15 shanxi hanzhong
tom 11 jiangshu nanjing
jerry 12 jiangshu nanjing
mike 13 jiangshu nanjing
john 14 jiangshu nanjing
mary 15 jiangshu nanjing
Time taken: 18.525 seconds, Fetched: 25 row(s)
左外連接(left outer join)
- 以連接中的左表為主:
select
s.name, s.age, s.addressid,
a.province, a.city
from
student s
left outer join
address a
on
s.addressid=a.addressid;
結果如下,可見name=mary的記錄,addressid等於5,在address中不存在addressid等於5的記錄,因此province和city字段都展示了NULL,而在前面使用inner join時,結果中沒有這條記錄:
Total MapReduce CPU Time Spent: 950 msec
OK
tom 11 1 guangdong guangzhou
jerry 12 2 guangdong shenzhen
mike 13 3 shanxi xian
john 14 4 shanxi hanzhong
mary 15 5 NULL NULL
Time taken: 18.442 seconds, Fetched: 5 row(s)
右外連接(right outer join)
和左連接類似,只不過是以右表為主,語法是right outer join:
select
s.name, s.age, s.addressid,
a.province, a.city
from
student s
right outer join
address a
on
s.addressid=a.addressid;
結果如下,可見city=nanjing的記錄,在student表中沒有一條記錄與之關聯,因此結果中展示了address的字段,而student的字段為NULL:
Total MapReduce CPU Time Spent: 970 msec
OK
tom 11 1 guangdong guangzhou
jerry 12 2 guangdong shenzhen
mike 13 3 shanxi xian
john 14 4 shanxi hanzhong
NULL NULL NULL jiangshu nanjing
Time taken: 18.294 seconds, Fetched: 5 row(s)
全外連接(full outer join)
查詢結果等於左外連接和右外連接之和,語法是full outer join:
select
s.name, s.age, s.addressid,
a.province, a.city
from
student s
full outer join
address a
on
s.addressid=a.addressid;
結果如下:
Total MapReduce CPU Time Spent: 2 seconds 630 msec
OK
tom 11 1 guangdong guangzhou
jerry 12 2 guangdong shenzhen
mike 13 3 shanxi xian
john 14 4 shanxi hanzhong
mary 15 5 NULL NULL
NULL NULL NULL jiangshu nanjing
Time taken: 22.189 seconds, Fetched: 6 row(s)
- 至此,常用HiveQL體驗完畢,希望能給您一些參考,接下來的章節會進一步學習HiveQL的特性;
你不孤單,欣宸原創一路相伴
歡迎關注公眾號:程序員欣宸
微信搜索「程序員欣宸」,我是欣宸,期待與您一同暢游Java世界...
https://github.com/zq2599/blog_demos