-- hive的庫、表等數據操作實際是hdfs系統中的目錄和文件,讓開發者可以通過sql語句, 像操作關系數據庫一樣操作文件內容。
一、hiveSQL轉化為MR過程
一直好奇hiveSQL轉化為MR過程,好奇hive是如何做到這些的,所以在網上找了幾篇相關博客,根據自己理解重新畫了一份執行過程圖,做筆記。
二、hive 執行過程中數據傾斜問題
1.描述:
數據傾斜主要表現在,MR程序執行過程中,reduce節點大部分執行完畢,但是有一個或者少數幾個節點運行很慢,導致整個程序的處理時間很長。這是因為該reduce處理節點對應的key對應數據條數遠超於其他key導致該節點處理數據量太大而不能和其他節點同步完成執行。簡而言之,解釋同一key對應數據條數太多導致。常見有空值key。
2.原因:
2.1、key分布不均勻。
2.2、業務數據本身的原因。
2.3、建表考慮不周。
2.4、某些SQL本身就有數據傾斜。
3.解決方式:
3.1、給key一個隨機值,打亂key,進行第一步操作,然后第二步去掉隨機值再處理。
3.2、參數調節:
hive.map.aggr = true Map 端部分聚合,相當於Combiner。
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 中),最后完成最終的聚合操作。
3.3、SQL語句調節:
3.3.1 大小表Join:使用map join讓小的維度表(1000條以下的記錄條數) 先進內存。在map端完成reduce.
3.3.2 大表Join大表:把空值的key變成一個字符串加上隨機數,把傾斜的數據分到不同的reduce上,由於null值關聯不上,處理后並不影響最終結果。
3.3.3 count distinct大量相同特殊值:count distinct時,將值為空的情況單獨處理,如果是計算count distinct,可以不用處理,直接過濾,在最后結果中加1。如果還有其他計算,需要進行group by,可以先將值為空的記錄單獨處理,再和其他計算結果進行union。
3.3.4 group by維度過小:采用sum() group by的方式來替換count(distinct)完成計算。
3.3.5 特殊情況特殊處理:在業務邏輯優化效果的不大情況下,有些時候是可以將傾斜的數據單獨拿出來處理。最后union回去。
3.4、map和reduce優化。
3.4.1 當出現小文件過多,需要合並小文件。可以通過set hive.merge.mapfiles=true來解決。
3.4.2 單個文件大小稍稍大於配置的block塊的大寫,此時需要適當增加map的個數。解決方法:set mapred.map.tasks個數
3.4.3 文件大小適中,但map端計算量非常大,如select id,count(*),sum(case when...),sum(case when...)...需要增加map個數。解決方法:set mapred.map.tasks個數,set mapred.reduce.tasks個數
4.Hive的優化:
4.1、配置fetch抓取:修改配置文件hive.fetch.task.conversion為more,修改之后全局查找和字段查找以及limit都不會觸發MR任務。
4.2、善用本地模式:大多數的Hadoop Job要求Hadoop提供完整的可擴展性來觸發大數據集,不過有時候hive的輸入數據量非常的小,這樣的情況下可能觸發任務的事件比執行的事件還長,我們就可以通過本地模式把小量的數據放到本地上面計算。
4.3、Group by:默認情況下,map階段同一key的數據會發給一個reduce,當一個key數據過大就會傾斜,並不是所有的聚合操作都需要reduce端完成,很多聚合操作都可以現在map端進行部分聚合,最后在reduce端得出最終結果。
4.3.1 開啟在map端聚合:hive.map.aggr = true。
4.3.2 在map端進行聚合操作的條目數:hive.groupby.mapaggr.checkinterval = 100000。
4.3.3 有數據傾斜的時候進行負載均衡:hive.groupby.skewindata = true。
4.4、行列過濾:列處理:只拿自己需要的列,如果有,盡量使用分區過濾。行處理:在分區裁剪的時候,當使用外關聯的時候,先完全關聯再過濾。
4.5、動態分區調整:(慎用)
4.5.1 開啟動態分區:hive.exec.dynamic.partition=true。
4.5.2 設置為非嚴格模式:hive.exec.dynamic.partiton.mode = nostrict。
4.5.3 實操:創建分區表、加載數據到分區表中、創建目標分區、設置動態分區、查看目標分區表的分區情況。
4.6、小文件進行合並:在map執行之前合並小文件,減少map的數量,設置 set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat。
4.7、調整map的數量和reduce的數量。
4.8、並行執行:在Hive中可能有很多個階段,不一定是一個階段,這些階段並非相互依賴的。然后這些階段可以並行完成,設置並行:set hive.exec.parallel = true。
4.9、JVM的重用,缺點是task槽會被占用,一直要等到任務完成才會釋放。
轉載:https://blog.csdn.net/weixin_41408329/article/details/106116543