Hive企業級性能優化(好文建議收藏)


Hive做爲大數據平臺舉足輕重的框架,以其穩定性和簡單易用性也成爲當前構建企業級數據倉庫時使用最多的框架之一。sql

可是若是咱們只侷限於會使用Hive,而不考慮性能問題,就難搭建出一個完美的數倉,因此Hive性能調優是咱們大數據從業者必須掌握的技能。本文將給你們講解Hive性能調優的一些方法及技巧。數據庫

本文首發於公衆號:五分鐘學大數據

Hive性能問題排查的方式

當咱們發現一條SQL語句執行時間過長或者不合理時,咱們就要考慮對SQL進行優化,優化首先得進行問題排查,那麼咱們能夠經過哪些方式進行排查呢。性能優化

常用關係型數據庫的同窗可能知道關係型數據庫的優化的訣竅-看執行計劃。 如Oracle數據庫,它有多種類型的執行計劃,經過多種執行計劃的配合使用,能夠看到根據統計信息推演的執行計劃,即Oracle推斷出來的未真正運行的執行計劃;還能夠看到實際執行任務的執行計劃;可以觀察到從數據讀取到最終呈現的主要過程和中間的量化數據。能夠說,在Oracle開發領域,掌握合適的環節,選用不一樣的執行計劃,SQL調優就不是一件難事。服務器

Hive中也有執行計劃,可是Hive的執行計劃都是預測的,這點不像Oracle和SQL Server有真實的計劃,能夠看到每一個階段的處理數據、消耗的資源和處理的時間等量化數據。Hive提供的執行計劃沒有這些數據,這意味着雖然Hive的使用者知道整個SQL的執行邏輯,可是各階段耗用的資源情況和整個SQL的執行瓶頸在哪裏是不清楚的網絡

想要知道HiveSQL全部階段的運行信息,能夠查看YARN提供的日誌。查看日誌的連接,能夠在每一個做業執行後,在控制檯打印的信息中找到。以下圖所示:數據結構

Hive提供的執行計劃目前能夠查看的信息有如下幾種併發

  1. 查看執行計劃的基本信息,即explain;
  2. 查看執行計劃的擴展信息,即explain extended;
  3. 查看SQL數據輸入依賴的信息,即explain dependency;
  4. 查看SQL操做相關權限的信息,即explain authorization;
  5. 查看SQL的向量化描述信息,即explain vectorization。

在查詢語句的SQL前面加上關鍵字explain是查看執行計劃的基本方法。 用explain打開的執行計劃包含如下兩部分:框架

  • 做業的依賴關係圖,即STAGE DEPENDENCIES;
  • 每一個做業的詳細信息,即STAGE PLANS。

Hive中的explain執行計劃詳解可看我以前寫的這篇文章jvm

Hive底層原理:explain執行計劃詳解分佈式

注:使用explain查看執行計劃是Hive性能調優中很是重要的一種方式,請務必掌握!

總結:Hive對SQL語句性能問題排查的方式

  1. 使用explain查看執行計劃;
  2. 查看YARN提供的日誌。

Hive性能調優的方式

爲何都說性能優化這項工做是比較難的,由於一項技術的優化,必然是一項綜合性的工做,它是多門技術的結合。咱們若是隻侷限於一種技術,那麼確定作很差優化的。

下面將從多個徹底不一樣的角度來介紹Hive優化的多樣性,咱們先來一塊兒感覺下。

1. SQL語句優化

SQL語句優化涉及到的內容太多,因篇幅有限,不能一一介紹到,因此就拿幾個典型舉例,讓你們學到這種思想,之後遇到相似調優問題能夠往這幾個方面多思考下。

1. union all

insert into table stu partition(tp) 
select s_age,max(s_birth) stat,'max' tp 
from stu_ori
group by s_age

union all

insert into table stu partition(tp) 
select s_age,min(s_birth) stat,'min' tp 
from stu_ori
group by s_age;

咱們簡單分析上面的SQl語句,就是將每一個年齡的最大和最小的生日獲取出來放到同一張表中,union all 先後的兩個語句都是對同一張表按照s_age進行分組,而後分別取最大值和最小值。對同一張表相同的字段進行兩次分組,這形成了極大浪費,咱們能不能改造下呢,固然是能夠的,爲你們介紹一個語法:
from ... insert into ... ,這個語法將from前置,做用就是使用一張表,能夠進行屢次插入操做:

--開啓動態分區 
set hive.exec.dynamic.partition=true; 
set hive.exec.dynamic.partition.mode=nonstrict; 

from stu_ori 

insert into table stu partition(tp) 
select s_age,max(s_birth) stat,'max' tp 
group by s_age

insert into table stu partition(tp) 
select s_age,min(s_birth) stat,'min' tp 
group by s_age;

上面的SQL就能夠對stu_ori表的s_age字段分組一次而進行兩次不一樣的插入操做。

這個例子告訴咱們必定要多瞭解SQL語句,若是咱們不知道這種語法,必定不會想到這種方式的

2. distinct

先看一個SQL,去重計數:

select count(1) 
from( 
  select s_age 
  from stu 
  group by s_age 
) b;

這是簡單統計年齡的枚舉值個數,爲何不用distinct?

select count(distinct s_age) 
from stu;

有人說由於在數據量特別大的狀況下使用第一種方式可以有效避免Reduce端的數據傾斜,可是事實如此嗎?

咱們先無論數據量特別大這個問題,就當前的業務和環境下使用distinct必定會比上面那種子查詢的方式效率高。緣由有如下幾點:

  1. 上面進行去重的字段是年齡字段,要知道年齡的枚舉值是很是有限的,就算計算1歲到100歲之間的年齡,s_age的最大枚舉值纔是100,若是轉化成MapReduce來解釋的話,在Map階段,每一個Map會對s_age去重。因爲s_age枚舉值有限,於是每一個Map獲得的s_age也有限,最終獲得reduce的數據量也就是map數量*s_age枚舉值的個數。
  2. distinct的命令會在內存中構建一個hashtable,查找去重的時間複雜度是O(1);group by在不一樣版本間變更比較大,有的版本會用構建hashtable的形式去重,有的版本會經過排序的方式, 排序最優時間複雜度沒法到O(1)。另外,第一種方式(group by)去重會轉化爲兩個任務,會消耗更多的磁盤網絡I/O資源。
  3. 最新的Hive 3.0中新增了 count(distinct ) 優化,經過配置 hive.optimize.countdistinct,即便真的出現數據傾斜也能夠自動優化,自動改變SQL執行的邏輯。
  4. 第二種方式(distinct)比第一種方式(group by)代碼簡潔,表達的意思簡單明瞭,若是沒有特殊的問題,代碼簡潔就是優!

這個例子告訴咱們,有時候咱們不要過分優化,調優講究適時調優,過早進行調優有可能作的是無用功甚至產生負效應,在調優上投入的工做成本和回報不成正比。調優須要遵循必定的原則

2. 數據格式優化

Hive提供了多種數據存儲組織格式,不一樣格式對程序的運行效率也會有極大的影響。

Hive提供的格式有TEXT、SequenceFile、RCFile、ORC和Parquet等。

SequenceFile是一個二進制key/value對結構的平面文件,在早期的Hadoop平臺上被普遍用於MapReduce輸出/輸出格式,以及做爲數據存儲格式。

Parquet是一種列式數據存儲格式,能夠兼容多種計算引擎,如MapRedcue和Spark等,對多層嵌套的數據結構提供了良好的性能支持,是目前Hive生產環境中數據存儲的主流選擇之一。

ORC優化是對RCFile的一種優化,它提供了一種高效的方式來存儲Hive數據,同時也可以提升Hive的讀取、寫入和處理數據的性能,可以兼容多種計算引擎。事實上,在實際的生產環境中,ORC已經成爲了Hive在數據存儲上的主流選擇之一。

咱們使用一樣數據及SQL語句,只是數據存儲格式不一樣,獲得以下執行時長:

數據格式 CPU時間 用戶等待耗時
TextFile 33分 171秒
SequenceFile 38分 162秒
Parquet 2分22秒 50秒
ORC 1分52秒 56秒
注: CPU時間:表示運行程序所佔用服務器CPU資源的時間。
*用戶等待耗時*:記錄的是用戶從提交做業到返回結果期間用戶等待的全部時間。

查詢TextFile類型的數據表耗時33分鐘, 查詢ORC類型的表耗時1分52秒,時間得以極大縮短,可見不一樣的數據存儲格式也能給HiveSQL性能帶來極大的影響。

3. 小文件過多優化

小文件若是過多,對 hive 來講,在進行查詢時,每一個小文件都會當成一個塊,啓動一個Map任務來完成,而一個Map任務啓動和初始化的時間遠遠大於邏輯處理的時間,就會形成很大的資源浪費。並且,同時可執行的Map數量是受限的。

因此咱們有必要對小文件過多進行優化,關於小文件過多的解決的辦法,我以前專門寫了一篇文章講解,具體可查看:

解決hive小文件過多問題

4. 並行執行優化

Hive會將一個查詢轉化成一個或者多個階段。這樣的階段能夠是MapReduce階段、抽樣階段、合併階段、limit階段。或者Hive執行過程當中可能須要的其餘階段。默認狀況下,Hive一次只會執行一個階段。不過,某個特定的job可能包含衆多的階段,而這些階段可能並不是徹底互相依賴的,也就是說有些階段是能夠並行執行的,這樣可能使得整個job的執行時間縮短。若是有更多的階段能夠並行執行,那麼job可能就越快完成。

經過設置參數hive.exec.parallel值爲true,就能夠開啓併發執行。在共享集羣中,須要注意下,若是job中並行階段增多,那麼集羣利用率就會增長。

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

固然得是在系統資源比較空閒的時候纔有優點,不然沒資源,並行也起不來。

5. 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都結束了纔會釋放。

6. 推測執行優化

在分佈式集羣環境下,由於程序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的推測執行:

set hive.mapred.reduce.tasks.speculative.execution=true

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


公衆號【五分鐘學大數據】,大數據領域原創技術號

最後

代碼優化原則:

  • 理透需求原則,這是優化的根本;
  • 把握數據全鏈路原則,這是優化的脈絡;
  • 堅持代碼的簡潔原則,這讓優化更加簡單;
  • 沒有瓶頸時談論優化,這是自尋煩惱。

相關文章
相關標籤/搜索