hive sql 如何解決資料傾斜
場景:
我有接近7億條網站訪問瀏覽資料要做一次 按 host(域名) 分割槽,訪問時間進行排序(取最先訪問) 說白了就是row_number over(partition by host order by ftime)。 突然發現會報錯:
FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask
現象就是 reduce 99% 快一個小時,一直99%
這時候你要知道,你很可能遇到了資料傾斜的場景了。
方法一:
檢視執行計劃
explain 你的sql
例如:
說白了就是map 端有key ,reduce 也有key
你需要設定一些引數在map端 先聚合,這樣key到reduce 分組的時候壓力少點。
設定引數:
set hive.groupby.skewindata=true;
set hive.map.aggr=true;
set hive.vectorized.execution.enabled=true;
set hive.vectorized.execution.reduce.enabled = true;
set hive.exec.compress.output=true;
前兩個分別是 reduce 和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 中),最後完成最終的聚合操作。
set hive.map.aggr=true;
map端的提高聚合效能。
後面三個是向量計算和輸出壓縮。
這樣如果沒解決了的話可以嘗試對key進行隨機賦值,相當於Java自定義partition 的過程。
select case when userid is null then cast ( rand ( 47 )* 100000 as i nt )
我沒怎麼用過。
最後我做了host 的分組統計,觀察了資料分佈。發現前二的log數量 host 總量佔2/7,於是我放棄了Top2的計算,這樣能順利
跑出結果了。然後對top2進行統計。在union all 一下 之前的結果。特殊資料特殊對待。
適用場景: 資料傾斜欄位穩定,長期。
業務上可變通。