Hive調優(調優過程包括調整數據傾斜)

一個Hive查詢生成多個map reduce job,一個map reduce job又有map,reduce,spill,shuffle,sort等多個階段,因此針對hive查詢的優化能夠大體分爲針對M/R中單個步驟的優化,針對M/R全局的優化,和針對整個查詢(多M/R job)的優化。算法

Map階段的優化,主要是肯定合適的map數。那麼首先要了解map數也就是切 片的計算公式,即:sql

塊大小和切片的最大值求的最小值和最大切片求最大值。app

在hive中min的默認值是1B,max的默認值是256MB分佈式

 

num_map_tasks = max[${mapred.min.split.size}, min(${dfs.block.size}, ${mapred.max.split.size})]oop

通過以上的分析,在設置map個數的時候,能夠簡單的總結爲如下幾點:
(1)若是想增長map個數,則設置mapred.map.tasks 爲一個較大的值。
(2)若是想減少map個數,則設置mapred.min.split.size 爲一個較大的值。
(3)若是輸入中有不少小文件,依然想減小map個數,則須要將小文件merger爲大文件,而後使用準則2。性能

Reduce階段的優化優化

是指前面流程圖中的reduce phase(實際的reduce計算)而非圖中整個reduce task。Reduce階段優化的主要工做也是選擇合適的reduce task數量,跟上面的map優化相似。spa

reduce優化時,能夠直接設置mapred.reduce.tasks參數從而直接指定reduce的個數。線程

Map與Reduce之間的優化調試

所謂map和reduce之間,主要有3道工序。首先要把map輸出的結果進行排序後作成中間文件,其次這個中間文件就能分發到各個reduce,最後reduce端在執行reduce phase以前把收集到的排序子文件合併成一個排序文件。

 

第一個階段中,因爲內存不夠,數據可能沒辦法在內存中一次性排序完成,那麼就只能把局部排序的文件先保存到磁盤上,這個動做叫spill,而後spill出來的多個文件能夠在最後進行merge。若是發生spill,能夠經過設置io.sort.mb來增大mapper輸出buffer的大小,避免spill的發生。另外合併時能夠經過設置io.sort.factor來使得一次性可以合併更多的數據。調試參數的時候,一個要看spill的時間成本,一個要看merge的時間成本,還須要注意不要撐爆內存(io.sort.mb是算在map的內存裏面的)。

 

關於文件從map端copy到reduce端,默認狀況下在5%的map完成的狀況下reduce就開始啓動copy,這個有時候是很浪費資源的,因爲reduce一旦啓動就被佔用,一直等到map所有完成,收集到全部數據才能夠進行後面的動做,因此咱們能夠等比較多的map完成以後再啓動reduce流程,這個比例能夠經過mapred.reduce.slowstart. completed.maps去調整,他的默認值就是5%。若是以爲這麼作會減慢reduce端copy的進度,能夠把copy過程的線程增大。

文件格式的優化

 

文件格式方面有兩個問題,一個是給輸入和輸出選擇合適的文件格式,另外一個則是小文件問題。小文件問題在目前的hive環境下已經獲得了比較好的解決,hive的默認配置中就能夠在小文件輸入時自動把多個文件合併給1個map處理(固然,若是能直接讀取大文件更好),輸出時若是文件很小也會進行一輪單獨的合併,因此這裏就不專門討論了。

關於文件格式,Hive中目前主要是3種,textfile,sequencefile和rcfile。整體上來講,rcfile的壓縮比例和查詢時間稍好一點,因此推薦使用。

Job總體優化

Job執行模式(本地執行v.s.分佈式執行)、索引、Join算法、以及數據傾斜

Job執行模式

Hadoop的map reduce job能夠有3種模式執行,即本地模式,僞分佈式,還有真正的分佈式。

可是實際上對於處理數據量很是小的job,直接啓動分佈式job會消耗大量資源,而真正執行計算的時間反而很是少。這個時候就應該使用本地模式執行mr job,這樣執行的時候不會啓動分佈式job,執行速度就會快不少。

設置執行模式的主要參數有三個,一個是hive.exec.mode.local.auto,把他設爲true就可以自動開啓local mr模式。可是這還不足以啓動local mr,輸入的文件數量和數據量大小必需要控制,這兩個參數分別爲hive.exec.mode.local.auto.tasks.max和hive.exec.mode.local.auto.inputbytes.max,默認值分別爲4和128MB,即默認狀況下,map處理的文件數不超過4個而且總大小小於128MB就啓用local mr模式。

Join算法

當兩個表中有一個是小表的時候,就能夠考慮用map join了,由於小表複製的代價會好過大表shuffle的代價。使用map join的配置方法有兩種,一種直接在sql中寫hint,語法是/*+MAPJOIN (tbl)*/,其中tbl就是你想要作replication的表。另外一種方法是設置hive.auto.convert.join = true,這樣hive會自動判斷當前的join操做是否合適作map join,主要是找join的兩個表中有沒有小表。至於多大的表算小表,則是由hive.smalltable.filesize決定,默認25MB。可是在小表join大表的時候要考慮小表的記錄的條目數,每一個條目數佔200字節,有時候可能大概80M的小表它的實際佔用空間是1G多,會撐爆內存

數據傾斜

group by形成的傾斜和join形成的傾斜須要分開看。group by形成的傾斜有兩個參數能夠解決,一個是hive.map.aggr,默認值已經爲true,意思是會作map端的combiner。

另外一個參數是hive.groupby.skewindata。這個參數的意思是作reduce操做的時候,拿到的key並非全部相同值給同一個reduce,而是隨機分發,而後reduce作聚合,作完以後再作一輪MR,拿前面聚合過的數據再算結果

SQL總體優化

在hive生成的多個job中,在有些狀況下job之間是能夠並行的,典型的就是子查詢。當須要執行多個子查詢union all或者join操做的時候,job間並行就可使用了。

設置job間並行的參數是hive.exec.parallel,將其設爲true便可。默認的並行度最高爲8,也就是容許sql中8個job並行。若是想要更高的並行度,能夠經過hive.exec.parallel. thread.number參數進行設置,但要避免設置過大而佔用過多資源。

相關文章
相關標籤/搜索