Hive SQL的各種優化方法基本 都和數據傾斜密切相關。
Hive的優化分為join相關的優化和join無關的優化,從項目的實際來說,join相關的優化占了Hive優化的大部分內容,而join相關的優化又分為mapjoin可以解決的join優化和mapjoin無法解決的join優化。
1、數據傾斜
傾斜來自於統計學里的偏態分布。所謂偏態分布,即統計數據峰值與平均值不相等的頻率分布,根據峰值小於或大於平均值可分為正偏函數和負偏函數,其偏離的程度可用偏態系數刻畫。
對應分布式數據處理來說,希望數據平均分布到每個處理節點。如果以每個處理節點為X軸,每個節點處理的數據為Y軸,我希望的柱狀圖如下:
但是實際上由於業務數據本身的問題或者分布算法的問題,每個節點分配到的數據量很可能是下面的樣式:
更極端情況出現下面的樣式:
也就是說,只有待分到最多數據的節點處理完數據,整個數據處理任務才算完成,此時分布式的意義大大折扣了。實際上,即使每個節點分配到的數據量大致相同,數據仍然可能傾斜,
比如考慮統計詞頻的極端問題,如果某個節點分配的詞都是一個詞,那么顯然此節點需要的耗時將很長。
Hive的優化正是采用各種措施和方法對上述場景的傾斜問題進行優化和處理。
2、Hive優化
在實際的Hive SQL開發的過程中,Hive SQL 性能的問題上實際上只有一小部分和數據傾斜有關,很多時候,Hive SQL運行慢是由於開發人員對於使用的數據了解不夠以及一些不良的習慣引起的。
開發人員需要確定以下幾點:
1、 需要計算的指標真的需要從數據倉庫公共明細層來自行匯總嗎? 是不是數據公共層團隊開發公共匯總層已經可以滿足自己的需求?對應大眾的、KPI相關的指標等通常設計良好的數據倉庫公共層
肯定已經包含了,直接使用即可。
2、真的需要掃描那么多分區嗎,比如對於銷售事務明細表來說,掃描一年的分區和掃描一周的分區所帶來的計算、IO開銷完全是兩個數量級,所耗費時間肯定是不同的,所以開發人員要仔細考慮因為需求,
盡量不浪費計算和存儲資源。
3、盡量不要使用select * from your_table這樣的方式,用到哪些列就指定哪些列,另外WHERE條件中盡量添加過濾條件,以去掉無關的行,從而減少整個MapReduce任務寵需要處理、分發的數據量。
4、輸入文件不要是大量的小文件,Hive默認的Input Split是128MB(可配置),小文件可先合並成大文件。
3、join無關的優化
Hive SQL性能問題基本上大部分都是和JOIN相關,對於和join無關的問題主要有group by相關的傾斜和count distinct相關的優化
3.1、group by引起的傾斜優化
group by引起的傾斜主要是輸入數據行按照group by列分別布均勻引起的,比如,假設按照供應商對銷售明細事實表來統計訂單數,那么部分大供應商的訂單量顯然非常大,而多數供應商的訂單量就一般,
由於group by 的時候是按照供應商的ID分發到每個Reduce Task,那么此時分配到大供應商的Reduce task就分配了更多的訂單,從而導致數據傾斜。
對應group by引起的數據傾斜,優化措施非常簡單,只需要設置下面參數即可:
set hive.map.aggr = true
set hive.groupby.skewindata = true
此時,Hive在數據傾斜的時候回進行負載均衡。
3.2、count distinct優化
在Hive開發過程中,應該小心使用count distinct,因為很容易引起性能問題,比如下面的SQL:
select count(distinct user) from some_table;
由於必須去重,因此Hive將會把Map階段的輸出全部分布到一個Reduce Task上,此時很容易引起性能問題,對於這種情況,可以通過先group by再count的方式優化,優化后的SQL如下:
select count(*)
from (select user from some_table group by user) temp;
其原理為:利用group by去重,再統計group by 的行數目。
參考資料:《離線和實時大數據開發實戰》