Hive 優化

Hive 針對不同的查詢進行了優化,優化可以通過配置進行控制,本文將介紹部分優化的策略以及優化控制選項。

列裁剪(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 合併文件的大小
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章