Hive資料傾斜

獵手家園發表於2016-05-02

傾斜的原因:

  使map的輸出資料更均勻的分佈到reduce中去,是我們的最終目標。由於Hash演算法的侷限性,按key Hash會或多或少的造成資料傾斜。大量經驗表明資料傾斜的原因是人為的建表疏忽或業務邏輯可以規避的。

 

解決思路:

  Hive的執行是分階段的,map處理資料量的差異取決於上一個stage的reduce輸出,所以如何將資料均勻的分配到各個reduce中,就是解決資料傾斜的根本所在

 

具體辦法:

記憶體最佳化和I/O最佳化:

  驅動表:使用大表做驅動表,以防止記憶體溢位;Join最右邊的表是驅動表;Mapjoin無視join順序,用大表做驅動表;StreamTable。

 1. Mapjoin是一種避免避免資料傾斜的手段

  允許在map階段進行join操作,MapJoin把小表全部讀入記憶體中,在map階段直接拿另外一個表的資料和記憶體中表資料做匹配,由於在map是進行了join操作,省去了reduce執行的效率也會高很多

 

在《hive:join遇到問題》有具體操作

  在對多個表join連線操作時,將小表放在join的左邊,大表放在Jion的右邊,

  在執行這樣的join連線時小表中的資料會被快取到記憶體當中,這樣可以有效減少發生記憶體溢位錯誤的機率

 2. 設定引數

  hive.map.aggr = true

  hive.groupby.skewindata=true 還有其他引數

3.SQL語言調節

  比如: group by維度過小時:採用sum() group by的方式來替換count(distinct)完成計算

4.StreamTable

  將在reducer中進行join操作時的小table放入記憶體,而大table透過stream方式讀取

5.索引

Hive從0.80開始才有,提供了一個Bitmap點陣圖索引,索引可以加快GROUP BY查詢語句的執行速度,用的較少。

 

其他最佳化:

1、 列裁剪(Column pruning):只有需要用到的列才進行輸出

2、 謂詞下推(Predicate pushdown):儘早進行資料過濾(見圖表 7中,下面為先處理的邏

輯),減少後續處理的資料量

3、 分割槽裁剪(Partition pruning):只讀取滿足分割槽條件的檔案

4、 map-join:對於join中一些小檔案,可以在map階段進行join操作,見3.2.2節map-join部分

5、 join-reordering:將在reducer中進行join操作時的小table放入記憶體,而大table透過

stream方式讀取

6、 Group-by最佳化: 進行區域性聚合進行最佳化(包括hash-based和sort-based),對於skew

的key(key的row num和size在reduce時非常不均)可以進行兩次map-reduce的方式最佳化 

 

Hive的配置引數比較保守,所以效率會比較差一點,修改配置會讓查詢效率有比較大的提升,記錄幾個對查詢效率影響比較重要的引數。

 

後設資料:

巢狀SQL並行執行最佳化:

set hive.exec.parallel=true;

set hive.exec.parallel.thread.number=16;

 

排序最佳化

   Order by 實現全域性排序,一個reduce實現,效率低

   Sort by 實現部分有序,單個reduce輸出的結果是有序的,效率高,通常和DISTRIBUTE BY關鍵字一起使用(DISTRIBUTE BY關鍵字 可以指定map 到 reduce端的分發key)

   CLUSTER BY col1 等價於DISTRIBUTE BY col1 SORT BY col1.

 

合併小檔案

   檔案數目過多,會給 HDFS 帶來壓力,並且會影響處理效率,可以透過合併 Map 和 Reduce 的結果檔案來儘量消除這樣的影響

   hive.merge.mapfiles = true是否和並 Map 輸出檔案,預設為 True

   hive.merge.mapredfiles = false是否合併 Reduce 輸出檔案,預設為 False

   hive.merge.size.per.task = 256*1000*1000合併檔案的大小。

   這裡的引數沒有寫到上面的表格裡是因為這是可以根據任務不同臨時設定的,而不一定非要是全域性設定。有時候全域性設定了反而對大檔案的操作有效能影響。

 

使用分割槽,RCFilelzoORCFile

   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)

相關文章