通過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;
如果我們需要在查詢語句中呼叫外部指令碼,比如python,則我們可以使用transform,map,reduce等子句。
比如,我們希望過濾掉所有不及格的學生記錄,只輸出及格學生的成績資訊。
#! /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語句指定輸出的列。
直接程式設計使用hadoop的mapreduce是一件比較費時的事情。hive則大大簡化了這個操作。
和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;
和傳統sql類似,hive提供了left outer join,right outer join,full out 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連線以提高效率,比如:
select /*+mapjoin(teacher) */ a.stuno,b.teachernamefrom student a join teacher b on a.classno = b.classno;
以上紅色標記部分採用了c的注釋風格。
當連線時用到不等值判斷時,也比較適合map連線。具體原因需要深入了解hive和mapreduce的工作原理。
執行以下語句將返回所有班級平均分的最高記錄。
select max(**gscore) as mascore
from
(select classno,**g(score) as **gscore from student group byclassno) a;
輸出結果:
80.66666666666667
以上語句中紅色部分為乙個子查詢,且別名為a。返回的子查詢結果和乙個表類似,可以被繼續查詢。
和傳統資料庫中的檢視類似,hive的檢視只是乙個定義,檢視資料並不會儲存到檔案系統中。同樣,檢視是唯讀的。
執行以下兩個命令:
create view **g_score as
select classno,**g(score) as **gscore from student groupby classno;
select max(**gscore) as mascore
from **g_score;
可以看到輸出結果和上例中的結果是一樣的。
hive查詢優化總結
hive查詢優化總結 儲存,學習,分享 join查詢操作的基本原則 應該將條目少的表 子查詢放在 join 操作符的左邊。原因是在 join 操作的 reduce 階段,位於 join 操作符左邊的表的內容會被載入進記憶體,將條目少的表放在左邊,可以有效減少發生記憶體溢位錯誤的機率。join查詢操作...
Hive總結(五)hive日誌
日誌記錄了程式執行的過程,是一種查詢問題的利器。hive中的日誌分為兩種 1.系統日誌,記錄了hive的運 況,錯誤狀況。2.job 日誌,記錄了hive 中job的執行的歷史過程。系統日誌儲存在什麼地方呢 在hive conf hive log4j.properties 檔案中記錄了hive日誌的...
Hive總結(五)hive日誌
日誌記錄了程式執行的過程,是一種查詢問題的利器。hive中的日誌分為兩種 1.系統日誌,記錄了hive的運 況,錯誤狀況。2.job 日誌,記錄了hive 中job的執行的歷史過程。系統日誌儲存在什麼地方呢 在hive conf hive log4j.properties 檔案中記錄了hive日誌的...