Hive總結(十二)Hive查詢高階

2022-09-08 15:24:08 字數 3896 閱讀 3164

通過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日誌的...