Join查找操做的基本原則:應該將條目少的表/子查詢放在 Join 操做符的左邊。緣由是在 Join 操做的 Reduce 階段,位於 Join 操做符左邊的表的內容會被加載進內存,將條目少的表放在左邊,能夠有效減小發生內存溢出錯誤的概率。sql
Join查找操做中若是存在多個join,且全部參與join的表中其參與join的key都相同,則會將全部的join合併到一個mapred程序中。json
案例:緩存
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1) 在一個mapre程序中執行joinapp
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2) 在兩個mapred程序中執行join負載均衡
Map join的關鍵在於join操做中的某個表的數據量很小,案例:函數
SELECT /*+ MAPJOIN(b) */ a.key, a.value性能
FROM a join b on a.key = b.key 優化
Mapjoin 的限制是沒法執行a FULL/RIGHT OUTER JOIN b,和map join相關的hive參數:hive.join.emit.interval hive.mapjoin.size.key hive.mapjoin.cache.numrowsxml
因爲join操做是在where操做以前執行,因此當你在執行join時,where條件並不能起到減小join數據的做用;案例:排序
SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key)
WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'
最好修改成:
SELECT a.val, b.val FROM a LEFT OUTER JOIN b
ON (a.key=b.key AND b.ds='2009-07-07' AND a.ds='2009-07-07')
在join操做的每個mapred程序中,hive都會把出如今join語句中相對靠後的表的數據stream化,相對靠前的變的數據緩存在內存中。固然,也能夠手動指定stream化的表:SELECT /*+ STREAMTABLE(a) */ a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)
Map端聚合,首先在map端進行初步聚合,最後在reduce端得出最終結果,相關參數:
· hive.map.aggr = true是否在 Map 端進行聚合,默認爲 True
· hive.groupby.mapaggr.checkinterval = 100000在 Map 端進行聚合操做的條目數目
數據傾斜聚合優化,設置參數hive.groupby.skewindata = true,當選項設定爲 true,生成的查詢計劃會有兩個 MR Job。第一個 MR Job 中,Map 的輸出結果集合會隨機分佈到 Reduce 中,每一個 Reduce 作部分聚合操做,並輸出結果,這樣處理的結果是相同的 Group By Key 有可能被分發到不一樣的 Reduce 中,從而達到負載均衡的目的;第二個 MR Job 再根據預處理的數據結果按照 Group By Key 分佈到 Reduce 中(這個過程能夠保證相同的 Group By Key 被分佈到同一個 Reduce 中),最後完成最終的聚合操做。
文件數目過多,會給 HDFS 帶來壓力,而且會影響處理效率,能夠經過合併 Map 和 Reduce 的結果文件來消除這樣的影響:
· hive.merge.mapfiles = true是否和並 Map 輸出文件,默認爲 True
· hive.merge.mapredfiles = false是否合併 Reduce 輸出文件,默認爲 False
· hive.merge.size.per.task = 256*1000*1000合併文件的大小
經過left outer join進行查詢,(假設B表中包含另外的一個字段 key1
select a.key from a left outer join b on a.key=b.key where b.key1 is null
經過left semi join 實現 in
SELECT a.key, a.val FROM a LEFT SEMI JOIN b on (a.key = b.key)
Left semi join 的限制:join條件中右邊的表只能出如今join條件中。
Order by 實現全局排序,一個reduce實現,效率低
Sort by 實現部分有序,單個reduce輸出的結果是有序的,效率高,一般和DISTRIBUTE BY關鍵字一塊兒使用(DISTRIBUTE BY關鍵字 能夠指定map 到 reduce端的分發key)
CLUSTER BY col1 等價於DISTRIBUTE BY col1 SORT BY col1
Hive中的每一個分區都對應hdfs上的一個目錄,分區列也不是表中的一個實際的字段,而是一個或者多個僞列,在表的數據文件中實際上並不保存分區列的信息與數據。Partition關鍵字中排在前面的爲主分區(只有一個),後面的爲副分區
靜態分區:靜態分區在加載數據和使用時都須要在sql語句中指定
案例:(stat_date='20120625',province='hunan')
動態分區:使用動態分區須要設置hive.exec.dynamic.partition參數值爲true,默認值爲false,在默認狀況下,hive會假設主分區時靜態分區,副分區使用動態分區;若是想都使用動態分區,須要設置set hive.exec.dynamic.partition.mode=nostrick,默認爲strick
案例:(stat_date='20120625',province)
Hive支持在group by時對同一列進行屢次distinct操做,卻不支持在同一個語句中對多個列進行distinct操做。
注意事項:在使用自定義的mapred腳本時,關鍵字MAP REDUCE 是語句SELECT TRANSFORM ( ... )的語法轉換,並不意味着使用MAP關鍵字時會強制產生一個新的map過程,使用REDUCE關鍵字時會產生一個red過程。
自定義的mapred腳本能夠是hql語句完成更爲複雜的功能,可是性能比hql語句差了一些,應該儘可能避免使用,若有可能,使用UDTF函數來替換自定義的mapred腳本
UDTF將單一輸入行轉化爲多個輸出行,而且在使用UDTF時,select語句中不能包含其餘的列,UDTF不支持嵌套,也不支持group by 、sort by等語句。若是想避免上述限制,須要使用lateral view語法,案例:
select a.timestamp, get_json_object(a.appevents, '$.eventid'), get_json_object(a.appenvets, '$.eventname') from log a;
select a.timestamp, b.*
from log a lateral view json_tuple(a.appevent, 'eventid', 'eventname') b as f1, f2;
其中,get_json_object爲UDF函數,json_tuple爲UDTF函數。
UDTF函數在某些應用場景下能夠大大提升hql語句的性能,如須要屢次解析json或者xml數據的應用場景。
Count和sum函數多是在hql語句中使用的最爲頻繁的兩個聚合函數了,可是在hive中count函數在計算distinct value時支持加入條件過濾。