大數據第五課-Hive調優

1、Fetch抓取

Fetch抓取是指,==Hive中對某些狀況的查詢能夠沒必要使用MapReduce計算==算法

例如:select * from score;sql

在這種狀況下,Hive能夠簡單地讀取employee對應的存儲目錄下的文件,而後輸出查詢結果到控制檯 apache

在hive-default.xml.template文件中 ==hive.fetch.task.conversion默認是more==,老版本hive默認是minimal,該屬性修改成more之後,app

在全局查找、字段查找、limit查找等都不走mapreduce。負載均衡

案例實操jvm

把 hive.fetch.task.conversion設置成==none==,而後執行查詢語句,都會執行mapreduce程序分佈式

set hive.fetch.task.conversion=none;
select * from score;
select s_id from score;
select s_id from score limit 3;

把hive.fetch.task.conversion設置成==more==,而後執行查詢語句,以下查詢方式都不會執行mapreduce程序。ide

set hive.fetch.task.conversion=more;
select * from score;
select s_id from score;
select s_id from score limit 3;

2、本地模式

在Hive客戶端測試時,默認狀況下是啓用hadoop的job模式,把任務提交到集羣中運行,這樣會致使計算很是緩慢;oop

Hive能夠經過本地模式在單臺機器上處理任務。對於小數據集,執行時間能夠明顯被縮短。性能

案例實操

--開啓本地模式,並執行查詢語句
set hive.exec.mode.local.auto=true;  //開啓本地mr
--設置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=5;
--執行查詢的sql語句
select * from student cluster by s_id;
--關閉本地運行模式
set hive.exec.mode.local.auto=false;
select * from student cluster by s_id;

3、表的優化

1 小表、大表 join

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

再進一步,可使用map join讓小的維度表(1000條如下的記錄條數)先進內存。在map端完成reduce。

2 大表 join 大表

空 key 過濾

有時join超時是由於某些key對應的數據太多,而相同key對應的數據都會發送到相同的reducer上,從而致使內存不夠。

此時咱們應該仔細分析這些異常的key,不少狀況下,這些key對應的數據是異常數據,咱們須要在SQL語句中進行過濾。

三、map join

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

 --開啓MapJoin參數設置
set hive.auto.convert.join = true;

四、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中),最後完成最終的聚合操做。

五、count(distinct)

數據量小的時候無所謂,數據量大的狀況下,因爲count distinct 操做須要用一個reduce Task來完成,這一個Reduce須要處理的數據量太大,就會致使整個Job很難完成,通常count distinct使用先group by 再count的方式替換

六、笛卡爾積

儘可能避免笛卡爾積,即避免join的時候不加on條件,或者無效的on條件

Hive只能使用1個reducer來完成笛卡爾積。

4、分區裁剪,列裁剪

  • 儘量早地過濾掉儘量多的數據量,避免大量數據流入外層SQL。

  • 列剪裁

    • 只獲取須要的列的數據,減小數據輸入。

  • 分區裁剪

    • 分區在hive實質上是目錄,分區裁剪能夠方便直接地過濾掉大部分數據。

    • 儘可能使用分區過濾,少用select *

5、並行執行

把一個sql語句中沒有相互依賴的階段並行去運行。提升集羣資源利用率

--開啓並行執行
set hive.exec.parallel=true;
--同一個sql容許最大並行度,默認爲8。
set hive.exec.parallel.thread.number=16;

6、嚴格模式

Hive提供了一個嚴格模式,能夠防止用戶執行那些可能意想不到的很差的影響的查詢。

經過設置屬性hive.mapred.mode值爲默認是非嚴格模式nonstrict 。開啓嚴格模式須要修改hive.mapred.mode值爲strict,開啓嚴格模式能夠禁止3種類型的查詢。

--設置非嚴格模式(默認)
set hive.mapred.mode=nonstrict;
--設置嚴格模式
set hive.mapred.mode=strict;

(1)對於分區表,除非where語句中含有分區字段過濾條件來限制範圍,不然不容許執行

--設置嚴格模式下 執行sql語句報錯; 非嚴格模式下是能夠的
select * from order_partition;
異常信息:Error: Error while compiling statement: FAILED: SemanticException [Error 10041]: No partition predicate found for Alias "order_partition" Table "order_partition" 

(2)對於使用了order by語句的查詢,要求必須使用limit語句

--設置嚴格模式下 執行sql語句報錯; 非嚴格模式下是能夠的
select * from order_partition where month='2019-03' order by order_price; 
異常信息:Error: Error while compiling statement: FAILED: SemanticException 1:61 In strict mode, if ORDER BY is specified, LIMIT must also be specified. Error encountered near token 'order_price'

(3)限制笛卡爾積的查詢,嚴格模式下,避免出現笛卡爾積的查詢

7、JVM重用

JVM重用是Hadoop調優參數的內容,其對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>

咱們也能夠在hive當中經過

 set  mapred.job.reuse.jvm.num.tasks=10;

這個設置來設置咱們的jvm重用

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

8、推測執行

在分佈式集羣環境下,由於程序Bug(包括Hadoop自己的bug),負載不均衡或者資源分佈不均等緣由,會形成同一個做業的多個任務之間運行速度不一致,有些任務的運行速度可能明顯慢於其餘任務(好比一個做業的某個任務進度只有50%,而其餘全部任務已經運行完畢),則這些任務會拖慢做業的總體執行進度。爲了不這種狀況發生,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>

關於調優這些推測執行變量,還很難給一個具體的建議。若是用戶對於運行時的誤差很是敏感的話,那麼能夠將這些功能關閉掉。若是用戶由於輸入數據量很大而須要執行長時間的map或者Reduce task的話,那麼啓動推測執行形成的浪費是很是巨大大。

9、數據壓縮

Hive表中間數據壓縮

#設置爲true爲激活中間數據壓縮功能,默認是false,沒有開啓
set hive.exec.compress.intermediate=true;
#設置中間數據的壓縮算法
set mapred.map.output.compression.codec= org.apache.hadoop.io.compress.SnappyCodec;

Hive表最終輸出結果壓縮

set hive.exec.compress.output=true;
set mapred.output.compression.codec = org.apache.hadoop.io.compress.SnappyCodec;

10、數據傾斜

一、合理設置Map數
2 、小文件合併
三、 複雜文件增長Map數
四、 合理設置Reduce數

 

 

 

把hive.fetch.task.conversion設置成==more==,而後執行查詢語句,以下查詢方式都不會執行mapreduce程序。

相關文章
相關標籤/搜索