Hive優(yōu)化的十大方法

Hive用的好,才能從數(shù)據(jù)中挖掘出更多的信息來。用過hive的朋友,我想或多或少都有類似的經(jīng)歷:一天下來,沒跑幾次hive,就到下班時間了。Hive在極大數(shù)據(jù)或者數(shù)據(jù)不平衡等情況下,表現(xiàn)往往一般,因此也出現(xiàn)了presto、spark-sql等替代品。這里重點(diǎn)講解hive的優(yōu)化方式,例如

優(yōu)化分組:set hive.auto.convert.join=true;

優(yōu)化表關(guān)聯(lián)內(nèi)存運(yùn)行:/*+MAPJOIN(t1,t3,t4)*/ 

一. 表連接優(yōu)化

  1. 將大表放后頭
    Hive假定查詢中最后的一個表是大表。它會將其它表緩存起來,然后掃描最后那個表。因此通常需要將小表放前面,或者標(biāo)記哪張表是大表:/*streamtable(table_name) */

  2. 使用相同的連接鍵
    當(dāng)對3個或者更多個表進(jìn)行join連接時,如果每個on子句都使用相同的連接鍵的話,那么只會產(chǎn)生一個MapReduce job。

  3. 盡量盡早地過濾數(shù)據(jù)
    減少每個階段的數(shù)據(jù)量,對于分區(qū)表要加分區(qū),同時只選擇需要使用到的字段。

  4. 盡量原子化操作
    盡量避免一個SQL包含復(fù)雜邏輯,可以使用中間表來完成復(fù)雜的邏輯

二. 用insert into替換union all
如果union all的部分個數(shù)大于2,或者每個union部分?jǐn)?shù)據(jù)量大,應(yīng)該拆成多個insert into 語句,實際測試過程中,執(zhí)行時間能提升50%。示例參考如下:

insert overwite table tablename partition (dt= ....)  

select ..... from ( select ... from A 
union all  
select ... from B  union all select ... from C ) R  

where ...;

可以改寫為:

insert into table tablename partition (dt= ....) select .... from A WHERE ...; 
insert into table tablename partition (dt= ....) select .... from B  WHERE ...; 
insert into table tablename partition (dt= ....) select .... from C WHERE ...;

三. order by & sort by
order by : 對查詢結(jié)果進(jìn)行全局排序消耗時間長,需要set hive.mapred.mode=nostrict
sort by : 局部排序,并非全局有序,提高效率。

四. transform+python
一種嵌入在hive取數(shù)流程中的自定義函數(shù),通過transform語句可以把在hive中不方便實現(xiàn)的功能在python中實現(xiàn),然后寫入hive表中。示例語法如下:

select transform({column names1})

using '**.py'

as {column names2}

from {table name}

如果除python腳本外還有其它依賴資源,可以使用ADD ARVHIVE。

五. limit 語句快速出結(jié)果
一般情況下,Limit語句還是需要執(zhí)行整個查詢語句,然后再返回部分結(jié)果。有一個配置屬性可以開啟,避免這種情況—對數(shù)據(jù)源進(jìn)行抽樣

hive.limit.optimize.enable=true --- 開啟對數(shù)據(jù)源進(jìn)行采樣的功能
hive.limit.row.max.size --- 設(shè)置最小的采樣容量
hive.limit.optimize.limit.file --- 設(shè)置最大的采樣樣本數(shù)

缺點(diǎn):有可能部分?jǐn)?shù)據(jù)永遠(yuǎn)不會被處理到

六. 本地模式
對于小數(shù)據(jù)集,為查詢觸發(fā)執(zhí)行任務(wù)消耗的時間>實際執(zhí)行job的時間,因此可以通過本地模式,在單臺機(jī)器上(或某些時候在單個進(jìn)程上)處理所有的任務(wù)。

set oldjobtracker=${hiveconf:mapred.job.tracker}; 
set mapred.job.tracker=local;  
set marped.tmp.dir=/home/edward/tmp;
set mapred.job.tracker=${oldjobtracker};
sql 語句

可以通過設(shè)置屬性hive.exec.mode.local.auto的值為true,來讓Hive在適當(dāng)?shù)臅r候自動啟動這個優(yōu)化,也可以將這個配置寫在$HOME/.hiverc文件中。
當(dāng)一個job滿足如下條件才能真正使用本地模式:

job的輸入數(shù)據(jù)大小必須小于參數(shù):hive.exec.mode.local.auto.inputbytes.max(默認(rèn)128MB)
job的map數(shù)必須小于參數(shù):hive.exec.mode.local.auto.tasks.max(默認(rèn)4)
job的reduce數(shù)必須為0或者1
可用參數(shù)hive.mapred.local.mem(默認(rèn)0)控制child的jvm使用的最大內(nèi)存數(shù)。

七. 并行執(zhí)行
Hive會將一個查詢轉(zhuǎn)化為一個或多個階段,包括:MapReduce階段、抽樣階段、合并階段、limit階段等。默認(rèn)情況下,一次只執(zhí)行一個階段。 不過,如果某些階段不是互相依賴,是可以并行執(zhí)行的。

set hive.exec.parallel=true,可以開啟并發(fā)執(zhí)行。
set hive.exec.parallel.thread.number=16; //同一個sql允許最大并行度,默認(rèn)為8。

會比較耗系統(tǒng)資源。

八. 調(diào)整mapper和reducer的個數(shù)

  1. Map階段優(yōu)化
    map個數(shù)的主要的決定因素有: input的文件總個數(shù),input的文件大小,集群設(shè)置的文件塊大?。J(rèn)128M,不可自定義)。參考舉例如下:

假設(shè)input目錄下有1個文件a,大小為780M,那么hadoop會將該文件a分隔成7個塊(6個128m的塊和1個12m的塊),從而產(chǎn)生7個map數(shù)
假設(shè)input目錄下有3個文件a,b,c,大小分別為10m,20m,130m,那么hadoop會分隔成4個塊(10m,20m,128m,2m),從而產(chǎn)生4個map數(shù)。
即如果文件大于塊大小(128m),那么會拆分,如果小于塊大小,則把該文件當(dāng)成一個塊。
map執(zhí)行時間:map任務(wù)啟動和初始化的時間+邏輯處理的時間。

減少map數(shù)
若有大量小文件(小于128M),會產(chǎn)生多個map,處理方法是:

set mapred.max.split.size=100000000; 
set mapred.min.split.size.per.node=100000000; 
set mapred.min.split.size.per.rack=100000000;  

前面三個參數(shù)確定合并文件塊的大小,大于文件塊大小128m的,按照128m來分隔,小于128m,大于100m的,按照100m來分隔,把那些小于100m的(包括小文件和分隔大文件剩下的)進(jìn)行合并。

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; – 執(zhí)行前進(jìn)行小文件合并。

增加map數(shù)
當(dāng)input的文件都很大,任務(wù)邏輯復(fù)雜,map執(zhí)行非常慢的時候,可以考慮增加Map數(shù),來使得每個map處理的數(shù)據(jù)量減少,從而提高任務(wù)的執(zhí)行效率。
set mapred.reduce.tasks=?

  1. Reduce階段優(yōu)化
    調(diào)整方式:
set mapred.reduce.tasks=?
set hive.exec.reducers.bytes.per.reducer = ?

一般根據(jù)輸入文件的總大小,用它的estimation函數(shù)來自動計算reduce的個數(shù):reduce個數(shù) = InputFileSize / bytes per reducer

九. 嚴(yán)格模式

set hive.marped.mode=strict --防止用戶執(zhí)行那些可能意想不到的不好的影響的查詢

(1)分區(qū)表,必須選定分區(qū)范圍
(2)對于使用order by的查詢,要求必須使用limit語句。因為order by為了執(zhí)行排序過程會將所有的結(jié)果數(shù)據(jù)分發(fā)到同一個reducer中進(jìn)行處理
(3)限制笛卡爾積查詢:兩張表join時必須有on語句

十. 數(shù)據(jù)傾斜
表現(xiàn):
任務(wù)進(jìn)度長時間維持在99%(或100%),查看任務(wù)監(jiān)控頁面,發(fā)現(xiàn)只有少量(1個或幾個)reduce子任務(wù)未完成。因為其處理的數(shù)據(jù)量和其他reduce差異過大。單一reduce的記錄數(shù)與平均記錄數(shù)差異過大,通??赡苓_(dá)到3倍甚至更多。 最長時長遠(yuǎn)大于平均時長。

原因:

(1)key分布不均勻
(2)業(yè)務(wù)數(shù)據(jù)本身的特性
(3)建表時考慮不周
(4)某些SQL語句本身就有數(shù)據(jù)傾斜
file

解決方案:參數(shù)調(diào)節(jié)

set hive.map.aggr=true

關(guān)注我的公眾號,后臺回復(fù)【JAVAPDF】獲取200頁面試題!
5萬人關(guān)注的大數(shù)據(jù)成神之路,不來了解一下嗎?
5萬人關(guān)注的大數(shù)據(jù)成神之路,真的不來了解一下嗎?
5萬人關(guān)注的大數(shù)據(jù)成神之路,確定真的不來了解一下嗎?

歡迎您關(guān)注《大數(shù)據(jù)成神之路》
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容