Hive優化(二)—具體優化操做

引語node

        上一篇介紹了關於Hive優化的一些基本概念,這一篇主要講hive性能優化的一些具體事項,這篇主要將對數據傾斜問題的優化,以及其餘的方面的一些優化。apache

數據傾斜

什麼是數據傾斜

        在Hadoop當項目中,數據傾斜能夠說是損害Hadoop性能的罪魁禍首。在運行Hadoop的任務過程中,咱們可能由於業務的須要,避免不了須要按照某個字段分組,去重,進行多表鏈接等操做,在這些操做當中一旦有些使用不當,就會很容易形成數據傾斜。一樣,當一個模型設計不合理時,job數量指定過多或者分區不恰當時也很容易影響Hadoop的性能。那麼什麼是數據傾斜?怎樣避免或者處理數據傾斜問題呢?接下來就爲你們介紹具體的關於解決數據傾斜問題的具體方案。性能優化

        數據傾斜就是key分佈不均勻,致使分發到不一樣的reduce上,個別reduce任務特別重,致使其餘reduce都完成,而這些個別的reduce遲遲不完成的狀況 。網絡

數據傾斜的緣由

        key分佈不均勻。jvm

        map端數據傾斜,輸入文件太多且大小不一 。分佈式

        reduce端數據傾斜,分區器問題。oop

        業務數據自己的特徵。性能

數據傾斜的症狀

        任務長時間維持在99%(或100%),查看任務監控頁面,發現只有少許(1個或幾個)reduce子任務未完成。大數據

        查看子任務,能夠看到本地讀寫數據量積累很是大,一般超過10GB能夠認定發生了數據傾斜。優化

        平均記錄數超過50w且最大記錄數超過平均記錄數的4配

        最長時長超過平均時長4分鐘,且最大時長超過平均時長的2倍

        通常來講集羣的總體性能,是由執行任務時間最長的那個節點決定的。因此,有效地解決數據傾斜問題,就能有效地提升整個集羣的性能。接下來咱們來看一下具體的解決方法吧。

數據傾斜—大大表關聯

        有時join超時是由於某些key對應的數據太多,而相同key對應的數據都會發送到相同的reducer上,從而致使內存不夠。此時咱們應該仔細分析這些異常的key,不少狀況下,這些key對應的數據是異常數據,咱們須要在SQL語句中進行過濾。同時當有篩選條件時,應該先按照條件進行過濾,而後在進行join,這樣能夠減小數據量。

數據傾斜—大小表關聯

        緣由:Hive在進行join時是以左邊的表爲準的,在join左邊的表的數據會首先讀入內存,若是左邊的表key比較集中,而表的數據量又比較大,這樣就會致使加入內存的數據過大,最終就會出現嚴重的數據傾斜。相反若是左邊的表,key相對分散,那麼讀入內存的數據會比較小,join任務執行會比較快,就不會出現數據傾斜的現象。

        解決思路:

        將key相對分散,而且將數據量小的表放在join的左邊,這樣能夠有效減小內存溢出錯誤發生的概率。

        使用map join讓小的維度表先進內存。使用map join,會將其中作鏈接的小表(全量數據)分發到全部 MapTask 端進行 Join,從 而避免reduceTask,前提要求是內存足以裝下該全量數據。

數據傾斜—聚合時存在大量特殊值

        緣由:作count distinct時,該字段存在大量值爲NULL或空的記錄。

        思路:count distinct時,將值爲空的狀況單獨處理,若是是計算count distinct,能夠不用處理,直接過濾,在最後結果中加1。   若是還有其餘計算,須要進行group by,能夠先將值爲空的記錄單獨處理,再和其餘計算結果進行union。

其餘hive優化

Hive的並行執行

        同步執行hive的多個階段,hive在執行過程,將一個查詢轉化成一個或者多個階段。某個特定的job可能包含衆多的階段,而這些階段可能並不是徹底相互依賴的,也就是說能夠並行執行的,這樣可能使得整個job的執行時間縮短。hive執行開啓:set hive.exec.parallel=true

設置本地運行

        Hive 在集羣上查詢時,默認是在集羣上N臺機器上運行, 須要多個機器進行協調運行,這個方式很好地解決了大數據量的查詢問題。可是當 Hive 查詢處理的數據量比較小時,其實沒有必要啓動分佈式模式去執行,由於以分佈式方式執行就涉及到跨網絡傳輸、多節點協調 等,而且消耗資源。這個時間能夠只使用本地模式來執行 mapreduce job,只在一臺機器上執行,速度會很快。啓動本地模式能夠經過配置參數來達到這個目的:

參數名 默認值 做用
set hive.exec.mode.local.auto false 是否讓hive在本地運行
hive.exec.mode.local.auto.input.files.max 4 是否啓用本地模式的task的最大個數
hive.exec.mode.local.auto.inputbytes.max 128M 是否啓動本地模式最大文件輸入大小

        參數說明:

                set hive.exec.mode.local.auto=true 開啓本地mr,只是打開 hive 自動判斷是否啓動本地模式的開關,也就是打開這個參數並不能保證啓動本地模式,是否啓動還要取決於 map 任務數量。

                set hive.exec.mode.local.auto.input.files.max 設置local mr的最大輸入文件個數,當輸入文件個數小於這個值時採用local mr的方式,默認爲4。

                hive.exec.mode.local.auto.inputbytes.max 當指定大小時,纔會啓動本地模式,不指定則默認不啓動。 若是當輸入文件大小小於此閾值時能夠自動在本地模式運行,默認是 128兆。

嚴格模式

        Hive中提供有嚴格模式,爲了防止一些查詢。出現很差的影響。例如笛卡兒積,在嚴格模式下是不能運行的。配置以下:

    <property>
        <name>hive.mapred.mode</name>
        <value>strict</value>
    </property>
    
  說明
    默認值爲:非嚴格模式 nonstrict
    開啓嚴格模式: strict
  開啓了嚴格模式,會對查詢語句進行一些限制: 
  1 對於分區表: 必須存在where語句對分區表中分區字段進行條件過濾,不然,不容許執行該查詢。
  2 對於使用order by的語句必須使用limit 進行限定,因爲order by 以後全部的數據都會被分到一個reduce中那這樣reduce操做的數據量太多了,可能時間過長卡死。因此爲了防止reduce時間過長,在order by的時候必須給定 limit 減小redue處理的數據量。
  3 限制了笛卡兒積的查詢,主要在多表join中會出現。笛卡兒積的出現會形成性能極大的消耗。

推測執行

        在Hadoop中,做業完成時間取決於最慢的任務完成時間。一個做業由若干個Map任務和Reduce任務構成。因集羣中的資源分配不均等、硬件老化、軟件Bug等,會致使某個任務運行的時間快或者某個任務運行的時間慢,或者某個任務在運行的時候直接卡死了。;爲了防止某些任務,在運行過程當中,拖慢了整個MR任務的進度。在運行慢的任務節點上開啓相同的任務,若是時間比原來的任務運行的快則直接輸出推測運行的任務 。

        典型案例:系統中有99%的Map任務都完成了,只有少數幾個Map總是進度很慢,完不成,怎麼辦?

        推測執行機制

                發現拖後腿的任務,好比某個任務運行速度遠慢於任務平均速度。爲拖後腿任務啓動一個備份任務,同時運行。誰先運行完,則採用誰的結果。

執行推測任務的前提條件

        (1)每一個task只能有一個備份任務;

        (2)當前job已完成的task必須不小於0.05(5%)

        (3)開啓推測執行參數設置。Hadoop2.7.2 mapred-site.xml文件中默認是打開的。

        <property>  
              <name>mapreduce.map.speculative</name>  
              <value>true</value>  
              <description>If true, then multiple instances of some map tasks may be executed in parallel.  
              </description>  
            </property>  
            <property>  
              <name>mapreduce.reduce.speculative</name>  
              <value>true</value>  
              <description>  
                  If true, then multiple instances of some reduce tasks may be executed in parallel.  
              </description>  
            </property>

        mapred.map.tasks.speculative.execution boolean true 若是任務運行變慢,該屬性決定了是否要啓動一個map任務的另一個實力

        mapred.reduce.tasks.speculative.execution boolean true 若是任務運行變慢,該屬性決定這是否須要啓動一個reduce任務

執行計劃

        Hive中提供的能夠查看Hql語句的執行計劃,在執行計劃中會生成抽象語法樹,在語法樹中會顯示HQL語句之間的依賴關係以及執行過程。經過這些執行的過程和依賴能夠對HQL語句進行優化

JVM重用

        正常狀況下,MapReduce啓動的JVM在完成一個task以後就退出了,可是若是任務花費時間很短,又要屢次啓動JVM的狀況下(好比對很大數據量進行計數操做),JVM的啓動時間就會變成一個比較大的overhead。在這種狀況下,可使用jvm重用的參數:set Mapred.Job.reuse.jvm.num.tasks = 5; 。其做用是讓一個jvm運行屢次任務以後再退出,節約JVM的啓動時間。

小文件的合併

        大量的小文件致使文件數目過多,例如當一個文件是130MB的時候,Hadoop會將這個文件分紅2個默認塊,一個是128MB剩餘的分一個2MB另外分一個,這樣就會給HDFS帶來壓力,對hive處理的效率影響比較大,對於小文件問題有兩種處理方法。

設置hive參數,將額外啓動一個MR Job打包小文件

hive.merge.mapfiles=true(默認值爲真) 是否合併Map輸出文件
hive.merge.mapredfiles=false(默認值爲假)是否合併Reduce 端輸出文件
hive.merge.size.per.task=256*1000*1000(默認值爲 256000000)合併文件的大小

        使用Combinefileinputformat,將多個小文件打包做爲一個總體的inputsplit,減小map任務數。前面三個參數肯定合併文件塊的大小,大於文件塊大小128m的,按照128m來分隔,小於128m,大於100m的,按照100m來分隔,把那些小於100m的(包括小文件和分隔大文件剩下的)進行合併

set mapred.max.split.size=100000000;
set mapred.min.split.size.per.node=100000000
set  Mapred.min.split.size.per.rack=100000000
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat

合理利用文件存儲格式

        建立表時,儘可能使用 orc、parquet 這些列式存儲格式,由於列式存儲的表,每一列的數據在物理上是存儲在一塊兒的,Hive查詢時會只遍歷須要列數據,大大減小處理的數據量。同時因爲parquet文件是以二進制存儲的,所以能夠減小文件的序列化和法序列化的操做,從而節省時間。

對文件進行適當的壓縮

        Hive 最終是轉爲 MapReduce 程序來執行的,而MapReduce 的性能瓶頸在於網絡 IO 和 磁盤 IO,要解決性能瓶頸,最主要的是減小數據量,對數據進行壓縮是個好的方式。壓縮 雖然是減小了數據量,可是壓縮過程要消耗CPU的,可是在Hadoop中, 每每性能瓶頸不在於CPU,CPU壓力並不大,因此壓縮充分利用了比較空閒的 CPU。

減小Job的數量

        對於一個job可以完成的任務,儘可能不要使用兩個job來完成,從而減小job初始化所須要的時間。

程序角度

        熟練使用SQL提升查詢,寫出高效率的查詢語句。

相關文章
相關標籤/搜索