Hive常見的優化方式

一、前言

Hive是基於Hadoop的一個數據倉庫工具,可以將結構化的數據文件映射爲一張表,並提供類SQL查詢功能。
本質是:將HQL轉化成MapReduce程序。此篇文章對於hive如何使用、如何配置及一些基礎性的知識不做闡述;直入重點聊一聊如何通過常見的一些手段方法提高hive的性能、提高執行效率。

二、調優

1.替換執行引擎爲tez

​ 在我之前的文章中已經講解了如何配置,傳送門

2.Fetch抓取

Fetch抓取是指,Hive中對某些情況的查詢可以不必使用MapReduce計算。例如:SELECT * FROM table在這種情況下,Hive可以簡單地讀取table表對應的存儲目錄下的文件,然後輸出查詢結果到控制檯。在hive-default.xml.template文件中hive.fetch.task.conversion默認是more,老版本hive默認是minimal,該屬性修改爲more以後,在全局查找、字段查找、limit查找等都不走mapreduce。

<property>
    <name>hive.fetch.task.conversion</name>
    <value>more</value>
    <description>
      Expects one of [none, minimal, more].
      Some select queries can be converted to single FETCH task minimizing latency.
      Currently the query should be single sourced not having any subquery and should not have
      any aggregations or distincts (which incurs RS), lateral views and joins.
      0. none : disable hive.fetch.task.conversion
      1. minimal : SELECT STAR, FILTER on partition columns, LIMIT only
      2. more  : SELECT, FILTER, LIMIT only (support TABLESAMPLE and virtual columns)
    </description>
  </property

3.本地模式

有時Hive的輸入數據量是非常小的。在這種情況下,爲查詢觸發執行任務消耗的時間可能會比實際job的執行時間要多的多。對於大多數這種情況,Hive可以通過本地模式在單臺機器上處理所有的任務。對於小數據集,執行時間可以明顯被縮短。如何判斷數據量的多少則根據輸入文件的數量、文件的個數來判斷(不建議全局開啓,根據實際任務開始臨時配置)。

#開啓本地mr
set hive.exec.mode.local.auto=true;
#設置local mr的最大輸入數據量,當輸入數據量小於這個值時採用local  mr的方式,默認爲134217728,即128M
set hive.exec.mode.local.auto.inputbytes.max=50000000;
#設置local mr的最大輸入文件個數,當輸入文件個數小於這個值時採用local mr的方式,默認爲4
set hive.exec.mode.local.auto.input.files.max=10;

4.MapJoin

如果不指定MapJoin或者不符合MapJoin的條件,那麼Hive解析器會將Join操作轉換成Common Join,即:在Reduce階段完成join。容易發生數據傾斜。可以用MapJoin把小表全部加載到內存在map端進行join,避免reducer處理。

#默認爲true
set hive.auto.convert.join = true;

#大表小表的閾值設置(默認25M一下認爲是小表)
set hive.mapjoin.smalltable.filesize=25000000;

早期的版本中需要我們手動開啓,對於大表join小表必須將小表放在大表前面才能起到效果;新版本中前後都已經得到了優化。但是具體控制大小表的閾值我們則可以根據實際自行控制。

5.Group By

默認情況下,Map階段同一Key數據分發給一個reduce,當一個key數據過大時就傾斜了。並不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端進行部分聚合,最後在Reduce端得出最終結果。

#開啓Map端聚合參數設置是否在Map端進行聚合,默認爲True
set hive.map.aggr = true

#在Map端進行聚合操作的條目數目
set hive.groupby.mapaggr.checkinterval = 100000

#有數據傾斜的時候進行負載均衡(默認是false)
set 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中),最後完成最終的聚合操作。

6.笛卡爾積

儘量避免笛卡爾積,join的時候不加on條件,或者無效的on條件,Hive只能使用1個reducer來完成笛卡爾積。

7.動態分區調整

關係型數據庫中,對分區表Insert數據時候,數據庫自動會根據分區字段的值,將數據插入到相應的分區中,Hive中也提供了類似的機制,即動態分區(Dynamic Partition),只不過,使用Hive的動態分區,需要進行相應的配置。

#開啓動態分區功能(默認true,開啓)
set hive.exec.dynamic.partition=true

#設置爲非嚴格模式(動態分區的模式,默認strict,表示必須指定至少一個分區爲靜態分區,nonstrict模式表示允許所有的分區字段都可以使用動態分區。)
set hive.exec.dynamic.partition.mode=nonstrict

#在所有執行MR的節點上,最大一共可以創建多少個動態分區。
set hive.exec.max.dynamic.partitions=1000

#)在每個執行MR的節點上,最大可以創建多少個動態分區。該參數需要根據實際的數據來設定。比如:源數據中包含了一年的數據,即day字段有365個值,那麼該參數就需要設置成大於365,如果使用默認值100,則會報錯。
set hive.exec.max.dynamic.partitions.pernode=100

#整個MR Job中,最大可以創建多少個HDFS文件。與上一個值可以保持一致,一個符合實際的較大數值
set hive.exec.max.created.files=100000

#當有空分區生成時,是否拋出異常。一般不需要設置。
set hive.error.on.empty.partition=false

8.執行推測

在實際中可能因爲種種原因,會造成同一個作業的多個任務之間運行速度不一致,有些任務的運行速度可能明顯慢於其他任務(比如一個作業的某個任務進度只有一半,而其他所有任務已經運行完畢),則這些任務會拖慢作業的整體執行進度。爲了避免這種情況發生,Hadoop採用了推測執行(Speculative Execution)機制,它根據一定的法則推測出“拖後腿”的任務,併爲這樣的任務啓動一個備份任務,讓該任務與原始任務同時處理同一份數據,並最終選用最先成功運行完成任務的計算結果作爲最終結果。
設置開啓推測執行參數:Hadoop的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>

hive本身也提供了配置項來控制reduce-side的推測執行:

  <property>
    <name>hive.mapred.reduce.tasks.speculative.execution</name>
    <value>true</value>
    <description>Whether speculative execution for reducers should be turned on. </description>
  </property>

不過hive本身也提供了配置項來控制reduce-side的推測執行:

  <property>
    <name>hive.mapred.reduce.tasks.speculative.execution</name>
    <value>true</value>
    <description>Whether speculative execution for reducers should be turned on. </description>
  </property>

9.JVM重用

JVM重用對Hive的性能具有非常大的影響,特別是對於很難避免小文件的場景或task特別多的場景,這類場景大多數執行時間都很短。Hadoop的默認配置通常是使用派生JVM來執行map和Reduce任務的。這時JVM的啓動過程可能會造成相當大的開銷,尤其是執行的job包含有成百上千task任務的情況。JVM重用可以使得JVM實例在同一個job中重新使用N次。N的值可以在Hadoop的mapred-site.xml文件中進行配置。通常在10-20之間,具體多少需要根據具體業務場景測試得出。

<property>
  <name>mapreduce.job.jvm.numtasks</name>
  <value>10</value>
  <description>How many tasks to run per jvm. If set to -1, there is
  no limit. 
  </description>
</property>

這個功能的缺點是,開啓JVM重用將一直佔用使用到的task插槽(任務隊列),以便進行重用,直到任務完成後才能釋放。如果某個“不平衡的”job中有某幾個reduce task執行的時間要比其他Reduce task消耗的時間多的多的話,那麼保留的插槽就會一直空閒着卻無法被其他的job使用,直到所有的task都結束了纔會釋放。

10.嚴格模式

Hive提供了一個嚴格模式,可以防止用戶執行那些可能意想不到的不好的影響的查詢。通過設置屬性hive.mapred.mode值爲默認是非嚴格模式nonstrict (建義生產環境開啓)。

<property>
  <name>hive.mapred.mode</name>
  <value>strict</value>
  <description>
   The mode in which the Hive operations are being performed. 
   In strict mode, some risky queries are not allowed to run. They include:
    Cartesian Product. --限制笛卡爾積的查詢
    No partition being picked up for a query. --對於分區表,除非where語句中含有分區字段過濾條件來限制範圍,否則不允許執行
    Comparing bigints and strings -- 比較bigints、strings
    Comparing bigints and 、doubles. -- 比較bigints、doubles
    Orderby without limit.  -- 對於使用了order by語句的查詢,要求必須使用limit語句
	</description>
</property>

11.並行執行

Hive會將一個查詢轉化成一個或者多個階段。這樣的階段可以是MapReduce階段、抽樣階段、合併階段、limit階段。或者Hive執行過程中可能需要的其他階段。默認情況下,Hive一次只會執行一個階段。不過,某個特定的job可能包含衆多的階段,而這些階段可能並非完全互相依賴的,也就是說有些階段是可以並行執行的,這樣可能使得整個job的執行時間縮短。不過,如果有更多的階段可以並行執行,那麼job可能就越快完成。通過設置參數hive.exec.parallel值爲true,就可以開啓併發執行。不過,在共享集羣中,需要注意下,如果job中並行階段增多,那麼集羣利用率就會增加。

#打開任務並行執行(默認false)
set hive.exec.parallel=true;
#同一個sql允許最大並行度,默認爲8。
set hive.exec.parallel.thread.number=16;
發佈了30 篇原創文章 · 獲贊 42 · 訪問量 7812
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章