Hive查詢

jopen 10年前發布 | 23K 次閱讀 Hive 數據挖掘

排序和聚集

通過Hive提供的order by子句可以讓最終的輸出結果整體有序。但是因為Hive是基于Hadoop之上的,要生成這種整體有序的結果,就必須強迫Hadoop只利用一個Reduce來完成處理。這種方式的副作用就是回降低效率。

如果你不需要最終結果整體有序,你就可以使用sort by子句來進行排序。這種排序操作只保證每個Reduce的輸出是有序的。如果你希望某些特定行被同一個Reduce處理,則你可以使用distribute子句來完成。比如:

表student(classNo,stuNo,score)數據如下:

C01  N0101      82

C01  N0102      59

C02  N0201      81

C01  N0103      65

C03  N0302      92

C02  N0202      82

C02  N0203      79

C03  N0301      56

C03  N0306      72

 

我們希望按照成績由低到高輸出每個班級的成績信息。執行以下語句:

Select classNo,stuNo,score from student distribute byclassNo sort by score;

輸出結果為:

C02  N0203      79

C02  N0201      81

C02  N0202      82

C03  N0301      56

C03  N0306      72

C03  N0302      92

C01  N0102      59

C01  N0103      65

C01  N0101      82

我們可以看到每一個班級里所有的學生成績是有序的。因為同一個classNo的記錄會被分發到一個單獨的reduce處理,而同時sort by保證了每一個reduce的輸出是有序的。

注意:

為了測試上例中的distribute by的效果,你應該首先設置足夠多的reduce。比如上例中有3個不同的classNo,則我們需要設置reduce個數至少為3或更多。如果設置的 reduce個數少于3,將會導致多個不同的classNo被分發到同一個reduce,從而不能產生你所期望的輸出。設置命令如下:

set mapred.reduce.tasks = 3;

MapReduce腳本

如果我們需要在查詢語句中調用外部腳本,比如Python,則我們可以使用transform,map,reduce等子句。

比如,我們希望過濾掉所有不及格的學生記錄,只輸出及格學生的成績信息。

新建一個Python腳本文件score_pass.py,內容如下:

#! /usr/bin/env python

import sys

for line in sys.stdin:

         (classNo,stuNo,score)= line.strip().split('\t')  

         ifint(score) >= 60:

                   print"%s\t%s\t%s" %(classNo,stuNo,score)

執行以下語句

add file /home/user/score_pass.py;

select transform(classNo,stuNo,score) using'score_pass.py' as classNo,stuNo,score from student;

輸出結果為:

C01  N0101      82

C02  N0201      81

C01  N0103      65

C03  N0302      92

C02  N0202      82

C02  N0203      79

C03  N0306      72

注意:

1) 以上Python腳本中,分隔符只能是制表符(\t)。同樣輸出的分隔符也必須為制表符。這個是有hive自身決定的,不能更改,不要嘗試使用其他分隔符,否則會報錯。同時需要調用strip函數,以去除掉行尾的換行符。(或者直接使用不帶參數的line.split()代替。

2) 使用腳本前,先使用add file語句注冊腳本文件,以便hive將其分發到Hadoop集群。

3) Transfom傳遞數據到Python腳本,as語句指定輸出的列。

連接(join)

直接編程使用Hadoop的MapReduce是一件比較費時的事情。Hive則大大簡化了這個操作。

內連接(inner join)

和SQL的內連相似。執行以下語句查詢每個學生的編號和教師名:

Select a.stuNo,b.teacherName from student a join teacherb on a.classNo = b.classNo;

輸出結果如下:

N0203      Sun

N0202      Sun

N0201      Sun

N0306      Wang

N0301      Wang

N0302      Wang

N0103      Zhang

N0102      Zhang

N0101      Zhang

注意:

數據文件內容請參照上一篇文章。

不要使用select xx from aa bb where aa.f=bb.f這樣的語法,hive不支持這種寫法。

如果需要查看hive的執行計劃,你可以在語句前加上explain,比如:

explain Select a.stuNo,b.teacherName from student a jointeacher b on a.classNo = b.classNo;

外連接(outer join)

和傳統SQL類似,Hive提供了left outer join,right outer join,full out join。

半連接(semi join)

Hive不提供in子查詢。此時你可以用leftsemi join實現同樣的功能。

執行以下語句:

Select * from teacher left semi join student onstudent.classNo = teacher.classNo;

輸出結果如下:

C02  Sun

C03  Wang

C01  Zhang

可以看出,C04 Dong沒有出現在查詢結果中,因為C04在表student中不存在。

注意:

右表(student)中的字段只能出現在on子句中,不能出現在其他地方,比如不能出現在select子句中。

Map連接(map join)

當一個表非常小,足以直接裝載到內存中去時,可以使用map連接以提高效率,比如:

Select /*+mapjoin(teacher) */a.stuNo,b.teacherNamefrom student a join teacher b on a.classNo = b.classNo;

以上紅色標記部分采用了C的注釋風格。

當連接時用到不等值判斷時,也比較適合Map連接。具體原因需要深入了解Hive和MapReduce的工作原理。

子查詢(sub query)

運行以下語句將返回所有班級平均分的最高記錄。

Select max(avgScore) as maScore

from

(Select classNo,avg(score) as avgScore from student group byclassNo) a;

輸出結果:

80.66666666666667

以上語句中紅色部分為一個子查詢,且別名為a。返回的子查詢結果和一個表類似,可以被繼續查詢。

視圖(view)

和傳統數據庫中的視圖類似,Hive的視圖只是一個定義,視圖數據并不會存儲到文件系統中。同樣,視圖是只讀的。

運行以下兩個命令:

Create view avg_score as

Select classNo,avg(score) as avgScore from student groupby classNo;

Select max(avgScore) as maScore

From avg_score;

可以看到輸出結果和上例中的結果是一樣的。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!