delete hive_Hive高级调优
Hive調優策略
Hive作為大數據領域常用的數據倉庫組件,在設計和開發階段需要注意效率。
影響Hive效率的不僅僅是數據量過大;數據傾斜、數據冗余、job(小文件多)或I/O過多、MapReduce分配不合理等因素都對Hive的效率有影響。
對Hive的調優既包含對HiveQL語句本身的優化,也包含Hive配置項和MR方面的調整。
從以下幾個方面調優:
1、架構調優2、參數調優
3、SQL優化
架構優化
執行引擎
Hive支持多種執行引擎,分別是MR、Tez、Spark、Flink,可以通過hive-site.xml文件中的hive.execution.engine屬性配置。
Tez是一個構建于YARN之上的支持復雜的DAG(有向無環圖)任務的數據處理框 架。由Hontonworks開源,將MapReduce的過程拆分成若干個子過程,同時可以 把多個mapreduce任務組合成一個較大的DAG任務,減少了MapReduce之間的文件存儲,同時合理組合其子過程從而大幅提升MR作業的性能。
Tez.png優化器
與關系型數據庫類似,Hive在真正執行的時候,會先先通過解釋器
生成AST抽象語法樹,然后再通過編譯器生成邏輯執行計劃,再通過優化器進行優化,優化后通過執行器生成物理執行計劃。而Hive有兩種優化器:
Vectorize(矢量化優化器)和Cost-Based Optimization(CBO成本優化器)
矢量化查詢優化(向量化優化器)
矢量化查詢(要求執行引擎為Tez)執行通過一次批量執行1024行,而不是每行一行來提高掃描、聚合、過濾器和和鏈接等操作的性能,這個功能明顯縮短查詢執行時間
##?默認?falseset?hive.vectorized.execution.enabled?=?true;?
##?默認?false
set?hive.vectorized.execution.reduce.enabled?=?true;?
備注:
要使用矢量化查詢執行,必須用ORC格式存儲數據
求執行引擎為Tez
成本優化器
Hive的CBO是基于Apache Calcite的,Hive的CBO通過查詢成本(有analyze收集的統計信息)會生成有效率的執行計劃,最終會較少執行的時間和資源利用,使用CBO的配置如下:
--從?v0.14.0默認?trueSET?hive.cbo.enable=true;
--?默認false?
SET?hive.compute.query.using.stats=true;?
--?默認false
SET?hive.stats.fetch.column.stats=true;?
--?默認true
SET?hive.stats.fetch.partition.stats=true;
定期執行表(分析的命令:analyze)的分析,分析后的數據放在元數據庫中。
大表小表join.png低版本情況下,小表在前的確效率高,高版本優化器已經做了優化。是因為小表的數據可能會放到內存里面,大表的數據內存存不下就會導致效率低。
把重復關聯鍵少的表放在join前面做關聯可以提高join的效率
分區表
對于一個比較大的表,將其設計成分區表,可以提升查詢的性能,對于一個特定分區的查詢,只會加載對應分區路徑的數據文件,所以執行速度比較快
分區字段的選擇,避免層級較深的分區,否則會造成太多的字文件夾,常見的分區字段:
日期或時間。如 year、month、day或者hour,當表中存在時間或者日期字段時
地理問題。如國家、省份、城市等
業務邏輯。如部門、銷售區域、客戶等等
分桶表
與分區表類似,分桶表的組織方式是將HDFS上的文件分割成多個文件。
分桶可以加快數據采樣,也可以提升join的性能,join的字段是分桶字段,因為分桶可以確保某一個key對應的數據在一個特定的桶內(文件),巧妙的選擇分桶字段,可以大幅度提升join性能。
通常情況下,分桶字段可以選擇經常用過濾操作或者join操作的字段
文件格式
在HiveQL的create table語句中,可以使用 stored as … 指定表的存儲格式。Hive表支持的存儲格式有TextFile、SequenceFile、RCFile、ORC、Parquet等。
存儲格式一般需要根據業務進行選擇,生產環境中絕大多數表都采用TextFile、 ORC、Parquet存儲格式之一。
TextFile是最簡單的存儲格式,它是純文本記錄,也是Hive的默認格式。其磁盤開銷 大,查詢效率低,更多的是作為跳板來使用。RCFile、ORC、Parquet等格式的表都不能由文件直接導入數據,必須由TextFile來做中轉。
Parquet和ORC都是Apache旗下的開源列式存儲格式。列式存儲比起傳統的行式存 儲更適合批量OLAP查詢,并且也支持更好的壓縮和編碼。選擇Parquet的原因主要 是它支持Impala查詢引擎,并且對update、delete和事務性操作需求很低。
數據壓縮
壓縮技術可以減少map與reduce之間的數據傳輸,從而可以提升查詢性能,關于壓 縮的配置可以在hive的命令行中或者hive-site.xml文件中進行配置。
--?默認是falseSET?hive.exec.compress.intermediate=true
開啟壓縮之后,可以選擇下面的壓縮格式:
壓縮格式.png關于壓縮的編碼器可以通過mapred-site.xml, hive-site.xml進行配置,也可以通過 命令行進行配置,如:
--?中間結果壓縮SET?hive.intermediate.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;
--?輸出結果壓縮
SET?hive.exec.compress.output=true;
SET?mapreduce.output.fileoutputformat.compress.codec?=?org.apache.hadoop.io.compress.SnappyCodc
設計階段要考慮的優化點:
1、執行引擎2、優化器
3、分區、分桶
4、文件格式
5、數據壓縮
參數優化
本地模式
當Hive處理的數據量較小的時,啟動分布式處理數據就會顯得浪費,因為可能啟動時間比處理數據時間還要長,Hive支持將作業動態的轉為本地模式,需要使用下面的配置:
--?默認?falseSET?hive.exec.mode.local.auto=true;?
--?默認128M
SET?hive.exec.mode.local.auto.inputbytes.max=50000000;?
?--?默認?4
SET?hive.exec.mode.local.auto.input.files.max=5;
一個作業只要滿足下面的條件,會啟用本地模式
輸入文件的大小小于 hive.exec.mode.local.auto.inputbytes.max 配置的大小
map任務的數量小于 hive.exec.mode.local.auto.input.files.max 配置的大小
reduce任務的數量是1或者0
嚴格模式
所謂嚴格模式就是不允許執行3種有風險的HQL語句
查詢分區表的時候不限定分區列的語句
兩個表join產生了笛卡爾積
用order by 來排序,但沒有指定limit
要開啟嚴格模式,需要將參數要開啟嚴格模式,需要將參數 hive.mapred.mode 設為strict(缺省值)。
該參數可以不在參數文件中定義,在執行SQL之前設置(set hive.mapred.mode=nostrict ),即在當前SQL不是嚴格模式。
JVM重用
默認情況下,Hadoop會為為一個map或者reduce啟動一個JVM,這樣可以并行執行map和reduce。
當map或者reduce是那種僅運行幾秒鐘的輕量級作業時,JVM啟動進程所耗費的時 間會比作業執行的時間還要長。Hadoop可以重用JVM,通過共享JVM以串行而非并行的方式運行map或者reduce。
JVM的重用適用于同一個作業的map和reduce,對于不同作業的task不能夠共享 JVM。如果要開啟JVM重用,需要配置一個作業最大task數量,默認值為1,如果設 置為-1,則表示不限制
#?代表同一個MR?job中順序執行的5個task重復使用一個JVM,減少啟動和關閉的開銷?SET?mapreduce.job.jvm.numtasks=5;
這個功能的缺點是,開啟JVM重用將一直占用使用到的task插槽,以便進行重用,直 到任務完成后才能釋放。如果某個“不平衡的”job中有某幾個reduce task執行的時間 要比其他Reduce task消耗的時間多的多的話,那么保留的插槽就會一直空閑著卻無 法被其他的job使用,直到所有的task都結束了才會釋放。
并行執行
Hive的查詢通常會被轉換成一系列的stage,這些stage之間并不是一直相互依賴 的,可以并行執行這些stage,通過下面的方式進行配置:
SET?hive.exec.parallel=true;?--?默認falseSET?hive.exec.parallel.thread.number=16;?--?默認8
并行執行可以增加集群資源的利用率,如果集群的資源使用率已經很高了,那么并 行執行的效果不會很明顯。
推測執行
在分布式集群環境下,因為程序Bug、負載不均衡、資源分布不均等原因,會造成同 一個作業的多個任務之間運行速度不一致,有些任務的運行速度可能明顯慢于其他任務(比如一個作業的某個任務進度只有50%,而其他所有任務已經運行完畢), 則這些任務會拖慢作業的整體執行進度。
為了避免這種情況發生,Hadoop采用了推測執行機制,它根據一定的規則推測出 “拖后腿”的任務,并為這樣的任務啟動一個備份任務,讓該任務與原始任務同時處理 同一份數據,并最終選用最先成功運行完成任務的計算結果作為最終結果。
set?mapreduce.map.speculative=trueset?mapreduce.reduce.speculative=true
set?hive.mapred.reduce.tasks.speculative.execution=true
合并小文件
在map執行前合并小文件,減少map數
set?hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
在Map-Reduce的任務結束時合并小文件
SET?hive.merge.mapfiles?=?true;
#?在?map-reduce?任務結束時合并小文件,默認false?
SET?hive.merge.mapredfiles?=?true;
#?合并文件的大小,默認256M
SET?hive.merge.size.per.task?=?268435456;
#?當輸出文件的平均大小小于該值時,啟動一個獨立的map-reduce任務進行文件merge?
SET?hive.merge.smallfiles.avgsize?=?16777216;
Fetch模式
Fetch模式是指Hive中對某些情況的查詢可以不必使用MR計算,select col1,col2 from tab;
可以簡單地讀取表對應的存儲目錄下的文件,然后輸出查詢結果到控制臺,在開啟fetch模式之后,在全局查找、字段查找、limit查找等都不啟動MR
#?Default?Value:?minimal?in?Hive?0.10.0?through?0.13.1,?more?in?Hive?0.14.0?and?laterset?hive.fetch.task.conversion=more
參數調整:
1、本地模式2、嚴格模式
3、JVM重用
4、并行執行
5、推測執行
6、合并小文件
7、fetch模式(規避沒有必要的MapReduce)
SQL優化
列裁剪和分區裁剪
列裁剪是在查詢時至讀取需要的列,避免查詢select * from tab這種;分區裁剪就是只讀取需要的分區,不需要的分區不需要讀取出來,分區表一定要跟上分區。
select?uid,?event_type,?record_data??from?calendar_record_log
?where?pt_date?>=?20190201?and?pt_date?<=?20190224
???and?status?=?0;
sort by 代替 order by
HiveQL中的order by與其他關系數據庫SQL中的功能一樣,是將結果按某字段全局排序,這會導致所有map端數據都進入一reduce中,在數據量大時可能會長時間計算不完。
如果使用sort by,那么還是會視情況啟動多個reducer進行排序,并且保證每個 reducer內局部有序。為了控制map端數據分配到reducer的key,往往還要配合 distribute by 一同使用。如果不加 distribute by 的話,map端數據就會隨機分配到 reducer。
group by 代替count(distinct)
當要統計某一列的去重數時,如果數據量很大,count(distinct) 會非常慢。原因與 order by類似,count(distinct)邏輯只會有很少的reducer來處理。此時可以用 group by 來改寫:
--?原始SQLselect?count(distinct?uid)
from?tab;
--?優化后的SQL?
select?count(1)
??from?(select?uid
??????????from?tab
group?by?uid)?tmp;
這樣寫會啟動兩個MR job(單純distinct只會啟動一個),所以要確保數據量大到啟動job的overhead遠小于計算耗時,才考慮這種方法。當數據集很小或者key的傾斜 比較明顯時,group by還可能會比distinct慢。
group by配置調整----map端預聚合
group by時,如果先起一個combiner在map端做部分預聚合,可以有效減少 shuffle數據量。
--?默認為trueset?hive.map.aggr?=?true
Map端進行聚合操作的條目數
set?hive.groupby.mapaggr.checkinterval?=?100000通過 hive.groupby.mapaggr.checkinterval 參數也可以設置map端預聚合的行 數閾值,超過該值就會分拆job,默認值10W。
group by配置調整----傾斜均衡置頂
group by時如果某些key對應的數據量過大,就會發生數據傾斜。Hive自帶了一個均衡數據傾斜的配置項 hive.groupby.skewindata ,默認值false。
其實現方法是在group by時啟動兩個MR job。第一個job會將map端數據隨機輸入 reducer,每個reducer做部分聚合,相同的key就會分布在不同的reducer中。第二 個job再將前面預處理過的數據按key聚合并輸出結果,這樣就起到了均衡的效果。
但是,配置項畢竟是死的,單純靠它有時不能根本上解決問題,建議了解數據傾斜 的細節,并優化查詢語句。
join的在基礎優化
hive join 的三種方式
common join
普通連接,在SQL中不特殊指定連接方式使用的都是這種普通連接,兩個數據在做連接之前,會先去做shuffle,如下圖,會將關聯id,相同的時候同一個區,再去真正的關聯
缺點:性能差(性能差的原因:要將數據分區,有shuffle)
優點:操作簡單,適應性強
common Join.pngmap join
map端連接,與普通連接的區別是這個連接中不會有reduce階段存在,連接在map端完成
適用場景:大表與小表連接,小表數據量應該能夠完全加載到內存,否則不適用
優點:在大小表連接時性能提升明顯,
備注:Hive 0.6 的時候默認認為寫在select 后面的是大表,前面的是小表, 或者使用 /*+mapjoin(map_table) */ select a., b. from a join b on a.id = b.id【要求小表在前,大表之后】
hive 0.7 的時候這個計算是自動化的,它首先會自動判斷哪個是小表,哪個是大 表,這個參數由(hive.auto.convert.join=true)來控制,然后控制小表的大小由 (hive.smalltable.filesize=25000000)參數控制(默認是25M),當小表超過這個 大小,hive 會默認轉化成common join。
Hive 0.8.1,hive.smalltable.filesize => hive.mapjoin.smalltable.filesize 缺點:使用范圍較小,只針對大小表且小表能完全加載到內存中的情況。
bucket map join
分桶連接:Hive 建表的時候支持hash 分區通過指定clustered by (col_name,xxx ) into number_buckets buckets 關鍵字.當連接的兩個表的join key 就是bucket column 的時候,就可以通過設置hive.optimize.bucketmapjoin= true 來執行優 化。
原理:通過兩個表分桶在執行連接時會將小表的每個分桶映射成hash表,每個task 節點都需要這個小表的所有hash表,但是在執行時只需要加載該task所持有大表分 桶對應的小表部分的hash表就可以,所以對內存的要求是能夠加載小表中最大的 hash塊即可。
注意點:小表與大表的分桶數量需要是倍數關系,這個是因為分桶策略決定的,分桶時會根據分桶字段對桶數取余后決定哪個桶的,所以要保證成倍數關系。
優點:比map join對內存的要求降低,能在逐行對比時減少數據計算量(不用比對 小表全量)
缺點:只適用于分桶表
利用map join特性
map join特別適合大小表join的情況。Hive會將build table和probe table在map端直接完成join過程,消滅了reduce,效率很高。
select?a.event_type,?b.upload_time?from?calendar_event_code?ainner?join?(
??select?event_type,?upload_time?from?calendar_record_log
where?pt_date?=?20190225
)?b?on?a.event_type?
map join的配置項是 hive.auto.convert.join ,默認值true。
當build table大小小于hive.mapjoin.smalltable.filesize 會啟用map join, 默認值25000000(約25MB)。還有 hive.mapjoin.cache.numrows ,表示緩存 build table的多少行數據到內存,默認值25000。
分桶表map join
map join對分桶表還有特別的優化。由于分桶表是基于一列進行hash存儲的,因此 非常適合抽樣(按桶或按塊抽樣)。它對應的配置項是 hive.optimize.bucketmapjoin 。
傾斜均衡配置項
這個配置與 group by 的傾斜均衡配置項異曲同工,通過 hive.optimize.skewjoin 來配置,默認false。如果開啟了,在join過程中Hive會將計數超過閾值 hive.skewjoin.key (默認 100000)的傾斜key對應的行臨時寫進文件中,然后再啟動另一個job做map join生 成結果。通過 hive.skewjoin.mapjoin.map.tasks 參數還可以控制第二個job的 mapper數量,默認10000。
去掉空值和無意義的值
日志類數據中往往會有一些項沒有記錄到,其值為null,或者空字符串、-1等。如果 缺失的項很多,在做join時這些空值就會非常集中,拖累進度【備注:這個字段是連接字段】。
若不需要空值數據,就提前寫 where 語句過濾掉。需要保留的話,將空值key用隨 機方式打散,例如將用戶ID為null的記錄隨機改為負值:
select?a.uid,?a.event_type,?b.nickname,?b.age?from?(select
(case?when?uid?is?null?then?cast(rand()*-10240?as?int)?else?uid?end)?as?uid,
??event_type?from?calendar_record_log
??where?pt_date?>=?20190201
)?a?left?outer?join?(
select?uid,nickname,age?from?user_info?where?status?=?4?)?b?on?a.uid?=?b.uid;
單獨處理傾斜的key
如果傾斜的 key 有實際的意義,一般來講傾斜的key都很少,此時可以將它們單獨抽 取出來,對應的行單獨存入臨時表中,然后打上一個較小的隨機數前綴(比如 0~9),最后再進行聚合。
不要一個Select語句中,寫太多的Join。一定要了解業務,了解數據。(A0-A9) 分成多條語句,分步執行;(A0-A4; A5-A9);先執行大表與小表的關聯;
調整Map數
通常情況下,作業會通過輸入數據的目錄產生一個或者多個map任務。主要因素包括:
輸入文件總數
輸入文件大小
HDFS文件塊大小
Map不是越多也好,而是合適的才是最好的。
如果一個任務有很多小文件(遠遠小于128M),每個小文件也會被當做成一個數據塊,用一個MapTask來完成,一個MapTask啟動和初始化時間遠遠大于處理時間,就會造成資源浪費,而且系統中可用的map是有限的。
對于小文件采用的策略是合并小文件。
每個map處理接近128M的文件塊,會有其他問題嗎。也不一定。
有一個125M的文件,一般情況下會用一個Map Task完成。假設這個文件字段很 少,但記錄數卻非常多。如果Map處理的邏輯比較復雜,用一個map任務去做,性 能也不好。
對于復雜文件采用的策略是增加 Map 數
computeSliteSize(max(minSize,?min(maxSize,?blocksize)))?=?blocksizeminSize?:?mapred.min.split.size?(默認值1)
maxSize?:?mapred.max.split.size?(默認值256M)
調整maxSize最大值。讓maxSize最大值低于blocksize就可以增加map的個數。?建議用set的方式,針對SQL語句進行調整。
調整Reduce數
reducer數量的確定方法比mapper簡單得多。使用參數 mapred.reduce.tasks可以直接設定reducer數量。如果未設置該參數,Hive會進行自行推測,邏輯如下:
參數hive.exec.reducers.bytes.per.reducer用來設定每個reducer能夠處理的最大數據量,默認值256M
參數hive.exec.reducers.max用來設定每個job的最大reducer數量,默認值999(1.2版本之前)或1009(1.2版本之后)
得出reducer數:reducer_num = Min(total_input_size / hive.exec.reducers.bytes.per.reducer,hive.exec.reducers.max )
即: min(輸入總數據量 / 256M, 1009)
reducer數量與輸出文件的數量相關。如果reducer數太多,會產生大量小文件,對 HDFS造成壓力。如果reducer數太少,每個reducer要處理很多數據,容易拖慢運行 時間或者造成OOM。
Hive優化小結
深入理解 Hadoop 的核心能力,對Hive優化很有幫助。Hadoop/Hive 處理數據過 程,有幾個顯著特征:
不怕數據多,就怕數據傾斜
對job數比較多的作業運行效率相對比較低,比如即使有幾百行的表,多次關聯多次匯總,產品十幾個jobs,執行時間也需要較長時間。MapReduce作業初始化的時間是比較長的。
對sum、count的聚合操作來說,不存在數據傾斜
count(distinct) 效率較低,數據量大容易出問題
從大的方面來說,優化可以從幾個方面
好的設計模型,事半功倍(該分區分區,該分桶分桶,壓縮、本地模式)
解決數據傾斜問題。僅僅依靠參數解決數據傾斜,是通用的優化手段,收獲有限。開發人員應該熟悉業務,了解數據規律,通過業務邏輯解決數據傾斜往往更可靠。
減少job數
設置合理的mapTask、reduceTask數
對小文件進行合并
優化整體,單一作業優化不如整體優化。
總結
以上是生活随笔為你收集整理的delete hive_Hive高级调优的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 太平久久一次能买多少?太平久久最新开售时
- 下一篇: 与AMD热恋不再 NVIDIA AI超算