列裁剪(Column Pruning)
在讀數據的時候,只讀取查詢中需要用到的列,而忽略其他列。例如,對於查詢:
SELECT a,b FROM T WHERE e < 10;
其中,T 包含 5 個列 (a,b,c,d,e),列 c,d 將會被忽略,只會讀取a, b, e 列
這個選項默認爲真: hive.optimize.cp = true
分區裁剪(Partition Pruning)
在查詢的過程中減少不必要的分區。例如,對於下列查詢:
SELECT * FROM (SELECT c1, COUNT(1) FROM T GROUP BY c1) subq WHERE subq.prtn = 100; SELECT * FROM T1 JOIN (SELECT * FROM T2) subq ON (T1.c1=subq.c2) WHERE subq.prtn = 100;
會在子查詢中就考慮 subq.prtn = 100 條件,從而減少讀入的分區數目。
此選項默認爲真:hive.optimize.pruner=true
Join
在使用寫有 Join 操作的查詢語句時有一條原則:應該將條目少的表/子查詢放在 Join 操作符的左邊。原因是在 Join 操作的 Reduce 階段,位於 Join 操作符左邊的表的內容會被加載進內存,將條目少的表放在左邊,可以有效減少發生 OOM 錯誤的機率。
對於一條語句中有多個 Join 的情況,如果 Join 的條件相同,比如查詢:
INSERT OVERWRITE TABLE pv_users SELECT pv.pageid, u.age FROM page_view p JOIN user u ON (pv.userid = u.userid) JOIN newuser x ON (u.userid = x.userid);
- 如果 Join 的 key 相同,不管有多少個表,都會則會合併爲一個 Map-Reduce
- 一個 Map-Reduce 任務,而不是 ‘n’ 個
- 在做 OUTER JOIN 的時候也是一樣
如果 Join 的條件不相同,比如:
INSERT OVERWRITE TABLE pv_users SELECT pv.pageid, u.age FROM page_view p JOIN user u ON (pv.userid = u.userid) JOIN newuser x on (u.age = x.age);
Map-Reduce 的任務數目和 Join 操作的數目是對應的,上述查詢和以下查詢是等價的:
INSERT OVERWRITE TABLE tmptable SELECT * FROM page_view p JOIN user u ON (pv.userid = u.userid); INSERT OVERWRITE TABLE pv_users SELECT x.pageid, x.age FROM tmptable x JOIN newuser y ON (x.age = y.age);
Map Join
Join 操作在 Map 階段完成,不再需要Reduce,前提條件是需要的數據在 Map 的過程中可以訪問到。比如查詢:
INSERT OVERWRITE TABLE pv_users SELECT /*+ MAPJOIN(pv) */ pv.pageid, u.age FROM page_view pv JOIN user u ON (pv.userid = u.userid);
可以在 Map 階段完成 Join,如圖所示:
相關的參數爲:
- hive.join.emit.interval = 1000 How many rows in the right-most join operand Hive should buffer before emitting the join result.
- hive.mapjoin.size.key = 10000
- hive.mapjoin.cache.numrows = 10000
Group By
- Map 端部分聚合:
- 並不是所有的聚合操作都需要在 Reduce 端完成,很多聚合操作都可以先在 Map 端進行部分聚合,最後在 Reduce 端得出最終結果。
- 基於 Hash
- 參數包括:
- hive.map.aggr = true 是否在 Map 端進行聚合,默認爲 True
- hive.groupby.mapaggr.checkinterval = 100000 在 Map 端進行聚合操作的條目數目
- 有數據傾斜的時候進行負載均衡
- hive.groupby.skewindata = false
- 當選項設定爲 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 合併文件的大小