Hive SQL優化

一個Hive查詢生成多個map reduce job,一個map reduce job又有map,reduce,spill,shuffle,sort等多個階段,因此針對hive查詢的優化能夠大體分爲針對MR中單個步驟的優化(其中又會有細分),針對MR全局的優化,和針對整個查詢(多MR job)的優化,下文會分別闡述。web

簡單查詢的Fetch Task功能;sql

在Hive中執行一個簡答的查詢功能(select * 除外),都會轉換爲mapreduce做業,提交到hadoop集羣上執行,這樣比較消耗時間,因此從Hive 0.10.0版本開始,Hive支持Fetch Task功能,開啓了這個功能後,咱們執行簡單的查詢語句(沒有函數,排序等的查詢語句)時,不會生成mapreduce做業,而直接使用Fetch Task從HDFS文件中查詢出數據,這樣對於簡單查詢效率會更高。app

配置Fetch Task的方式有如下三種:jvm

-1. set hive.fetch.task.conversion=more;
-2. hive --hiveconf hive.fetch.task.conversion=more;
-3. 修改hive-site.xml文件;
其中方法1和2,只對當前的會話有效,退出會話後,下次執行簡單查詢時,默認開啓mapreduce.
而方法3會永久有效;

 

 

Map階段的優化(map phase)

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

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

mapred.min.split.size指的是數據的最小分割單元大小。
mapred.max.split.size指的是數據的最大分割單元大小。
dfs.block.size指的是HDFS設置的數據塊大小。

通常來講dfs.block.size這個值是一個已經指定好的值,並且這個參數hive是識別不到的:oop

hive> set dfs.block.size;
      dfs.block.size is undefined

因此實際上只有mapred.min.split.sizemapred.max.split.size這兩個參數(本節內容後面就以min和max指代這兩個參數)來決定map數量。在hive中min的默認值是1B,max的默認值是256MB:性能

hive> set mapred.min.split.size;
mapred.min.split.size=1

hive> set mapred.max.split.size;
mapred.max.split.size=256000000

因此若是不作修改的話,就是1個map task處理256MB數據,咱們就以調整max爲主。經過調整max能夠起到調整map數的做用,減少max能夠增長map數,增大max能夠減小map數。須要提醒的是,直接調整mapred.map.tasks這個參數是沒有效果的fetch

調整大小的時機根據查詢的不一樣而不一樣,總的來說能夠經過觀察map task的完成時間來肯定是否須要增長map資源。若是map task的完成時間都是接近1分鐘,甚至幾分鐘了,那麼每每增長map數量,使得每一個map task處理的數據量減小,可以讓map task更快完成;而若是map task的運行時間已經不多了,好比10-20秒,這個時候增長map不太可能讓map task更快完成,反而可能由於map須要的初始化時間反而讓job整體速度變慢,這個時候反而須要考慮是否能夠把map的數量減小,這樣能夠節省更多資源給其餘Job。優化

 

Reduce階段的優化(reduce phase)

Reduce階段優化的主要工做也是選擇合適的reduce task數量,跟上面的map優化相似。
與map優化不一樣的是,reduce優化時,能夠直接設置mapred.reduce.tasks參數從而直接指定reduce的個數。固然直接指定reduce個數雖然比較方便,可是不利於自動擴展。Reduce數的設置雖然相較map更靈活,可是也能夠像map同樣設定一個自動生成規則,這樣運行定時job的時候就不用擔憂原來設置的固定reduce數會因爲數據量的變化而不合適。spa

Hive估算reduce數量的時候,使用的是下面的公式:

num_reduce_tasks = min[${hive.exec.reducers.max}, 
                       (${input.size} / ${ hive.exec.reducers.bytes.per.reducer})
                      ]

hive.exec.reducers.bytes.per.reducer默認爲1G,也就是每一個reduce處理至關於job輸入文件中1G大小的對應數據量,並且reduce個數不能超過一個上限參數值,這個參數的默認取值爲999。因此咱們也能夠用調整這個公式的方式調整reduce數量,在靈活性和定製性上取得一個平衡。

設置reduce數一樣也是根據運行時間做爲參考調整,而且能夠根據特定的業務需求、工做負載類型總結出經驗,因此再也不贅述。

 

Map與Reduce之間的優化(spill, copy, sort phase)

map phase和reduce phase之間主要有3道工序。首先要把map輸出的結果進行排序後作成中間文件,其次這個中間文件就能分發到各個reduce,最後reduce端在執行reduce phase以前把收集到的排序子文件合併成一個排序文件。須要強調的是,雖然這個部分能夠調的參數挺多,可是大部分在通常狀況下都是不要調整的,除非能精準的定位到這個部分有問題。

Spill 與 Sort

在spill階段,因爲內存不夠,數據可能沒辦法在內存中一次性排序完成,那麼就只能把局部排序的文件先保存到磁盤上,這個動做叫spill,而後spill出來的多個文件能夠在最後進行merge。若是發生spill,能夠經過設置io.sort.mb來增大mapper輸出buffer的大小,避免spill的發生。另外合併時能夠經過設置io.sort.factor使得一次性可以合併更多的數據,默認值爲10,也就是一次歸併10個文件。調試參數的時候,一個要看spill的時間成本,一個要看merge的時間成本,還須要注意不要撐爆內存(io.sort.mb是算在map的內存裏面的)。Reduce端的merge也是同樣能夠用io.sort.factor。通常狀況下這兩個參數不多須要調整,除非很明確知道這個地方是瓶頸。好比若是map端的輸出太大,考慮到map數不必定能很方便的調整,那麼這個時候就要考慮調大io.sort.mb(不過即便調大也要注意不能超過jvm heap size)。而map端的輸出很大,要麼是每一個map讀入了很大的文件(好比不能split的大gz壓縮文件),要麼是計算邏輯致使輸出膨脹了不少倍,都是比較少見的狀況。

Copy

這裏說的copy,通常叫作shuffle更加常見。可是因爲一開始的配圖以及MR job的web監控頁對這個環節都是叫copy phase,指代更加精確,因此這裏稱爲copy。

copy階段是把文件從map端copy到reduce端默認狀況下在5%的map完成的狀況下reduce就開始啓動copy,這個有時候是很浪費資源的,由於reduce一旦啓動就被佔用,一直等到map所有完成,收集到全部數據才能夠進行後面的動做,因此咱們能夠等比較多的map完成以後再啓動reduce流程,這個比例能夠經過mapred.reduce.slowstart.completed.maps去調整,他的默認值就是5%。若是以爲這麼作會減慢reduce端copy的進度,能夠把copy過程的線程增大tasktracker.http.threads能夠決定做爲server端的map用於提供數據傳輸服務的線程,mapred.reduce.parallel.copies能夠決定做爲client端的reduce同時從map端拉取數據的並行度(一次同時從多少個map拉數據),修改參數的時候這兩個注意協調一下,server端能處理client端的請求便可。

另外,在shuffle階段可能會出現的OOM問題,緣由比較複雜,通常認爲是內存分配不合理,GC沒法及時釋放內存致使。對於這個問題,能夠嘗試調低shuffle buffer的控制參數mapred.job.shuffle.input.buffer.percent這個比例值,默認值0.7,即shuffle buffer佔到reduce task heap size的70%。另外也能夠直接嘗試增長reduce數量。

 

文件格式的優化

文件格式方面有兩個問題,一個是給輸入和輸出選擇合適的文件格式,另外一個則是小文件問題。小文件問題在目前的hive環境下已經獲得了比較好的解決,hive的默認配置中就能夠在小文件輸入時自動把多個文件合併給1個map處理,輸出時若是文件很小也會進行一輪單獨的合併,因此這裏就不專門討論了。相關的參數能夠在這裏找到(http://blog.csdn.net/yfkiss/article/details/8590486)。

相關文章
相關標籤/搜索