Hive調(diào)優(yōu)策略

Hive調(diào)優(yōu)策略

Hive作為大數(shù)據(jù)領(lǐng)域常用的數(shù)據(jù)倉庫組件,在設(shè)計(jì)和開發(fā)階段需要注意效率漫萄。

影響Hive效率的不僅僅是數(shù)據(jù)量過大;數(shù)據(jù)傾斜堆生、數(shù)據(jù)冗余虐译、job(小文件多)或I/O過多、MapReduce分配不合理等因素都對(duì)Hive的效率有影響鹅龄。

對(duì)Hive的調(diào)優(yōu)既包含對(duì)HiveQL語句本身的優(yōu)化揩慕,也包含Hive配置項(xiàng)和MR方面的調(diào)整。

從以下幾個(gè)方面調(diào)優(yōu):

1扮休、架構(gòu)調(diào)優(yōu)
2迎卤、參數(shù)調(diào)優(yōu)
3、SQL優(yōu)化

架構(gòu)優(yōu)化

執(zhí)行引擎

Hive支持多種執(zhí)行引擎玷坠,分別是MR蜗搔、Tez、Spark八堡、Flink樟凄,可以通過hive-site.xml文件中的hive.execution.engine屬性配置。

Tez是一個(gè)構(gòu)建于YARN之上的支持復(fù)雜的DAG(有向無環(huán)圖)任務(wù)的數(shù)據(jù)處理框 架兄渺。由Hontonworks開源缝龄,將MapReduce的過程拆分成若干個(gè)子過程,同時(shí)可以 把多個(gè)mapreduce任務(wù)組合成一個(gè)較大的DAG任務(wù),減少了MapReduce之間的文件存儲(chǔ)二拐,同時(shí)合理組合其子過程從而大幅提升MR作業(yè)的性能服鹅。

Tez.png
優(yōu)化器

與關(guān)系型數(shù)據(jù)庫類似,Hive在真正執(zhí)行的時(shí)候百新,會(huì)先先通過解釋器

生成AST抽象語法樹企软,然后再通過編譯器生成邏輯執(zhí)行計(jì)劃,再通過優(yōu)化器進(jìn)行優(yōu)化饭望,優(yōu)化后通過執(zhí)行器生成物理執(zhí)行計(jì)劃仗哨。而Hive有兩種優(yōu)化器:

Vectorize(矢量化優(yōu)化器)和Cost-Based Optimization(CBO成本優(yōu)化器)

  • 矢量化查詢優(yōu)化(向量化優(yōu)化器)

矢量化查詢(要求執(zhí)行引擎為Tez)執(zhí)行通過一次批量執(zhí)行1024行,而不是每行一行來提高掃描铅辞、聚合厌漂、過濾器和和鏈接等操作的性能,這個(gè)功能明顯縮短查詢執(zhí)行時(shí)間

## 默認(rèn) false
set hive.vectorized.execution.enabled = true; 
## 默認(rèn) false
set hive.vectorized.execution.reduce.enabled = true; 

備注:

  • 要使用矢量化查詢執(zhí)行斟珊,必須用ORC格式存儲(chǔ)數(shù)據(jù)
  • 求執(zhí)行引擎為Tez
  • 成本優(yōu)化器

Hive的CBO是基于Apache Calcite的苇倡,Hive的CBO通過查詢成本(有analyze收集的統(tǒng)計(jì)信息)會(huì)生成有效率的執(zhí)行計(jì)劃,最終會(huì)較少執(zhí)行的時(shí)間和資源利用囤踩,使用CBO的配置如下:

--從 v0.14.0默認(rèn) true
SET hive.cbo.enable=true;
-- 默認(rèn)false 
SET hive.compute.query.using.stats=true; 
-- 默認(rèn)false
SET hive.stats.fetch.column.stats=true; 
-- 默認(rèn)true
SET hive.stats.fetch.partition.stats=true;

定期執(zhí)行表(分析的命令:analyze)的分析旨椒,分析后的數(shù)據(jù)放在元數(shù)據(jù)庫中。

大表小表join.png

低版本情況下堵漱,小表在前的確效率高综慎,高版本優(yōu)化器已經(jīng)做了優(yōu)化。是因?yàn)樾”淼臄?shù)據(jù)可能會(huì)放到內(nèi)存里面勤庐,大表的數(shù)據(jù)內(nèi)存存不下就會(huì)導(dǎo)致效率低示惊。

把重復(fù)關(guān)聯(lián)鍵少的表放在join前面做關(guān)聯(lián)可以提高join的效率

分區(qū)表

對(duì)于一個(gè)比較大的表,將其設(shè)計(jì)成分區(qū)表愉镰,可以提升查詢的性能米罚,對(duì)于一個(gè)特定分區(qū)的查詢,只會(huì)加載對(duì)應(yīng)分區(qū)路徑的數(shù)據(jù)文件岛杀,所以執(zhí)行速度比較快

分區(qū)字段的選擇阔拳,避免層級(jí)較深的分區(qū),否則會(huì)造成太多的字文件夾类嗤,常見的分區(qū)字段:

  • 日期或時(shí)間。如 year辨宠、month遗锣、day或者h(yuǎn)our,當(dāng)表中存在時(shí)間或者日期字段時(shí)
  • 地理問題嗤形。如國家精偿、省份、城市等
  • 業(yè)務(wù)邏輯。如部門笔咽、銷售區(qū)域搔预、客戶等等
分桶表

與分區(qū)表類似,分桶表的組織方式是將HDFS上的文件分割成多個(gè)文件叶组。

分桶可以加快數(shù)據(jù)采樣拯田,也可以提升join的性能,join的字段是分桶字段甩十,因?yàn)榉滞翱梢源_保某一個(gè)key對(duì)應(yīng)的數(shù)據(jù)在一個(gè)特定的桶內(nèi)(文件)船庇,巧妙的選擇分桶字段,可以大幅度提升join性能侣监。

通常情況下鸭轮,分桶字段可以選擇經(jīng)常用過濾操作或者join操作的字段

文件格式

在HiveQL的create table語句中,可以使用 stored as ... 指定表的存儲(chǔ)格式橄霉。 Hive表支持的存儲(chǔ)格式有TextFile窃爷、SequenceFile、RCFile姓蜂、ORC吞鸭、Parquet等。

存儲(chǔ)格式一般需要根據(jù)業(yè)務(wù)進(jìn)行選擇覆糟,生產(chǎn)環(huán)境中絕大多數(shù)表都采用TextFile刻剥、 ORC、Parquet存儲(chǔ)格式之一滩字。

TextFile是最簡單的存儲(chǔ)格式造虏,它是純文本記錄,也是Hive的默認(rèn)格式麦箍。其磁盤開銷 大漓藕,查詢效率低,更多的是作為跳板來使用挟裂。RCFile享钞、ORC、Parquet等格式的表都不能由文件直接導(dǎo)入數(shù)據(jù)诀蓉,必須由TextFile來做中轉(zhuǎn)栗竖。

Parquet和ORC都是Apache旗下的開源列式存儲(chǔ)格式。列式存儲(chǔ)比起傳統(tǒng)的行式存 儲(chǔ)更適合批量OLAP查詢渠啤,并且也支持更好的壓縮和編碼狐肢。選擇Parquet的原因主要 是它支持Impala查詢引擎,并且對(duì)update沥曹、delete和事務(wù)性操作需求很低份名。

數(shù)據(jù)壓縮

壓縮技術(shù)可以減少map與reduce之間的數(shù)據(jù)傳輸碟联,從而可以提升查詢性能,關(guān)于壓 縮的配置可以在hive的命令行中或者h(yuǎn)ive-site.xml文件中進(jìn)行配置僵腺。

-- 默認(rèn)是false
SET hive.exec.compress.intermediate=true

開啟壓縮之后鲤孵,可以選擇下面的壓縮格式:

壓縮格式.png

關(guān)于壓縮的編碼器可以通過mapred-site.xml, hive-site.xml進(jìn)行配置,也可以通過 命令行進(jìn)行配置辰如,如:

-- 中間結(jié)果壓縮
SET hive.intermediate.compression.codec=org.apache.hadoop.io.compress.SnappyCodec;
-- 輸出結(jié)果壓縮
SET hive.exec.compress.output=true;
SET mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodc

設(shè)計(jì)階段要考慮的優(yōu)化點(diǎn):

1普监、執(zhí)行引擎
2、優(yōu)化器
3丧没、分區(qū)鹰椒、分桶
4、文件格式
5呕童、數(shù)據(jù)壓縮

參數(shù)優(yōu)化

本地模式

當(dāng)Hive處理的數(shù)據(jù)量較小的時(shí)漆际,啟動(dòng)分布式處理數(shù)據(jù)就會(huì)顯得浪費(fèi),因?yàn)榭赡軉?dòng)時(shí)間比處理數(shù)據(jù)時(shí)間還要長夺饲,Hive支持將作業(yè)動(dòng)態(tài)的轉(zhuǎn)為本地模式奸汇,需要使用下面的配置:

-- 默認(rèn) false
SET hive.exec.mode.local.auto=true; 
-- 默認(rèn)128M
SET hive.exec.mode.local.auto.inputbytes.max=50000000; 
 -- 默認(rèn) 4
SET hive.exec.mode.local.auto.input.files.max=5;

一個(gè)作業(yè)只要滿足下面的條件,會(huì)啟用本地模式

  • 輸入文件的大小小于 hive.exec.mode.local.auto.inputbytes.max 配置的大小
  • map任務(wù)的數(shù)量小于 hive.exec.mode.local.auto.input.files.max 配置的大小
  • reduce任務(wù)的數(shù)量是1或者0
嚴(yán)格模式

所謂嚴(yán)格模式就是不允許執(zhí)行3種有風(fēng)險(xiǎn)的HQL語句

  • 查詢分區(qū)表的時(shí)候不限定分區(qū)列的語句
  • 兩個(gè)表join產(chǎn)生了笛卡爾積
  • 用order by 來排序往声,但沒有指定limit

要開啟嚴(yán)格模式擂找,需要將參數(shù)要開啟嚴(yán)格模式,需要將參數(shù) hive.mapred.mode 設(shè)為strict(缺省值)浩销。

該參數(shù)可以不在參數(shù)文件中定義贯涎,在執(zhí)行SQL之前設(shè)置(set hive.mapred.mode=nostrict ),即在當(dāng)前SQL不是嚴(yán)格模式。

JVM重用

默認(rèn)情況下慢洋,Hadoop會(huì)為為一個(gè)map或者reduce啟動(dòng)一個(gè)JVM塘雳,這樣可以并行執(zhí)行map和reduce。

當(dāng)map或者reduce是那種僅運(yùn)行幾秒鐘的輕量級(jí)作業(yè)時(shí)普筹,JVM啟動(dòng)進(jìn)程所耗費(fèi)的時(shí) 間會(huì)比作業(yè)執(zhí)行的時(shí)間還要長败明。Hadoop可以重用JVM,通過共享JVM以串行而非并行的方式運(yùn)行map或者reduce太防。

JVM的重用適用于同一個(gè)作業(yè)的map和reduce妻顶,對(duì)于不同作業(yè)的task不能夠共享 JVM。如果要開啟JVM重用蜒车,需要配置一個(gè)作業(yè)最大task數(shù)量讳嘱,默認(rèn)值為1,如果設(shè) 置為-1醇王,則表示不限制

# 代表同一個(gè)MR job中順序執(zhí)行的5個(gè)task重復(fù)使用一個(gè)JVM呢燥,減少啟動(dòng)和關(guān)閉的開銷 
SET mapreduce.job.jvm.numtasks=5;

這個(gè)功能的缺點(diǎn)是,開啟JVM重用將一直占用使用到的task插槽寓娩,以便進(jìn)行重用,直 到任務(wù)完成后才能釋放。如果某個(gè)“不平衡的”job中有某幾個(gè)reduce task執(zhí)行的時(shí)間 要比其他Reduce task消耗的時(shí)間多的多的話棘伴,那么保留的插槽就會(huì)一直空閑著卻無 法被其他的job使用寞埠,直到所有的task都結(jié)束了才會(huì)釋放。

并行執(zhí)行

Hive的查詢通常會(huì)被轉(zhuǎn)換成一系列的stage焊夸,這些stage之間并不是一直相互依賴 的仁连,可以并行執(zhí)行這些stage,通過下面的方式進(jìn)行配置:

SET hive.exec.parallel=true; -- 默認(rèn)false
SET hive.exec.parallel.thread.number=16; -- 默認(rèn)8

并行執(zhí)行可以增加集群資源的利用率阱穗,如果集群的資源使用率已經(jīng)很高了饭冬,那么并 行執(zhí)行的效果不會(huì)很明顯。

推測(cè)執(zhí)行

在分布式集群環(huán)境下揪阶,因?yàn)槌绦駼ug昌抠、負(fù)載不均衡、資源分布不均等原因鲁僚,會(huì)造成同 一個(gè)作業(yè)的多個(gè)任務(wù)之間運(yùn)行速度不一致炊苫,有些任務(wù)的運(yùn)行速度可能明顯慢于其他任務(wù)(比如一個(gè)作業(yè)的某個(gè)任務(wù)進(jìn)度只有50%,而其他所有任務(wù)已經(jīng)運(yùn)行完畢)冰沙, 則這些任務(wù)會(huì)拖慢作業(yè)的整體執(zhí)行進(jìn)度侨艾。

為了避免這種情況發(fā)生,Hadoop采用了推測(cè)執(zhí)行機(jī)制拓挥,它根據(jù)一定的規(guī)則推測(cè)出 “拖后腿”的任務(wù)唠梨,并為這樣的任務(wù)啟動(dòng)一個(gè)備份任務(wù),讓該任務(wù)與原始任務(wù)同時(shí)處理 同一份數(shù)據(jù)侥啤,并最終選用最先成功運(yùn)行完成任務(wù)的計(jì)算結(jié)果作為最終結(jié)果当叭。

set mapreduce.map.speculative=true
set mapreduce.reduce.speculative=true
set hive.mapred.reduce.tasks.speculative.execution=true
合并小文件
  • 在map執(zhí)行前合并小文件,減少map數(shù)
# 缺省參數(shù)
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
  • 在Map-Reduce的任務(wù)結(jié)束時(shí)合并小文件
# 在 map-only 任務(wù)結(jié)束時(shí)合并小文件愿棋,默認(rèn)true 
SET hive.merge.mapfiles = true;
# 在 map-reduce 任務(wù)結(jié)束時(shí)合并小文件科展,默認(rèn)false 
SET hive.merge.mapredfiles = true;
# 合并文件的大小,默認(rèn)256M
SET hive.merge.size.per.task = 268435456;
# 當(dāng)輸出文件的平均大小小于該值時(shí)糠雨,啟動(dòng)一個(gè)獨(dú)立的map-reduce任務(wù)進(jìn)行文件merge 
SET hive.merge.smallfiles.avgsize = 16777216;
Fetch模式

Fetch模式是指Hive中對(duì)某些情況的查詢可以不必使用MR計(jì)算才睹,select col1,col2 from tab;

可以簡單地讀取表對(duì)應(yīng)的存儲(chǔ)目錄下的文件,然后輸出查詢結(jié)果到控制臺(tái)甘邀,在開啟fetch模式之后琅攘,在全局查找、字段查找松邪、limit查找等都不啟動(dòng)MR

# Default Value: minimal in Hive 0.10.0 through 0.13.1, more in Hive 0.14.0 and later
set hive.fetch.task.conversion=more

參數(shù)調(diào)整:

1坞琴、本地模式
2、嚴(yán)格模式
3逗抑、JVM重用
4剧辐、并行執(zhí)行
5寒亥、推測(cè)執(zhí)行
6、合并小文件
7荧关、fetch模式(規(guī)避沒有必要的MapReduce)

SQL優(yōu)化

列裁剪和分區(qū)裁剪

列裁剪是在查詢時(shí)至讀取需要的列溉奕,避免查詢select * from tab這種;分區(qū)裁剪就是只讀取需要的分區(qū)忍啤,不需要的分區(qū)不需要讀取出來,分區(qū)表一定要跟上分區(qū)加勤。

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與其他關(guān)系數(shù)據(jù)庫SQL中的功能一樣,是將結(jié)果按某字段全局排序同波,這會(huì)導(dǎo)致所有map端數(shù)據(jù)都進(jìn)入一reduce中鳄梅,在數(shù)據(jù)量大時(shí)可能會(huì)長時(shí)間計(jì)算不完。

如果使用sort by未檩,那么還是會(huì)視情況啟動(dòng)多個(gè)reducer進(jìn)行排序戴尸,并且保證每個(gè) reducer內(nèi)局部有序。為了控制map端數(shù)據(jù)分配到reducer的key讹挎,往往還要配合 distribute by 一同使用校赤。如果不加 distribute by 的話,map端數(shù)據(jù)就會(huì)隨機(jī)分配到 reducer筒溃。

group by 代替count(distinct)

當(dāng)要統(tǒng)計(jì)某一列的去重?cái)?shù)時(shí)马篮,如果數(shù)據(jù)量很大,count(distinct) 會(huì)非常慢怜奖。原因與 order by類似浑测,count(distinct)邏輯只會(huì)有很少的reducer來處理。此時(shí)可以用 group by 來改寫:

-- 原始SQL
select count(distinct uid)
from tab;


-- 優(yōu)化后的SQL 
select count(1)
  from (select uid
          from tab
group by uid) tmp;

這樣寫會(huì)啟動(dòng)兩個(gè)MR job(單純distinct只會(huì)啟動(dòng)一個(gè))歪玲,所以要確保數(shù)據(jù)量大到啟動(dòng)job的overhead遠(yuǎn)小于計(jì)算耗時(shí)迁央,才考慮這種方法。當(dāng)數(shù)據(jù)集很小或者key的傾斜 比較明顯時(shí)滥崩,group by還可能會(huì)比distinct慢岖圈。

group by配置調(diào)整----map端預(yù)聚合

group by時(shí),如果先起一個(gè)combiner在map端做部分預(yù)聚合钙皮,可以有效減少 shuffle數(shù)據(jù)量蜂科。

-- 默認(rèn)為true
set hive.map.aggr = true

Map端進(jìn)行聚合操作的條目數(shù)

set hive.groupby.mapaggr.checkinterval = 100000

通過 hive.groupby.mapaggr.checkinterval 參數(shù)也可以設(shè)置map端預(yù)聚合的行 數(shù)閾值,超過該值就會(huì)分拆job短条,默認(rèn)值10W导匣。

group by配置調(diào)整----傾斜均衡置頂

group by時(shí)如果某些key對(duì)應(yīng)的數(shù)據(jù)量過大,就會(huì)發(fā)生數(shù)據(jù)傾斜茸时。Hive自帶了一個(gè)均衡數(shù)據(jù)傾斜的配置項(xiàng) hive.groupby.skewindata 贡定,默認(rèn)值false。

其實(shí)現(xiàn)方法是在group by時(shí)啟動(dòng)兩個(gè)MR job。第一個(gè)job會(huì)將map端數(shù)據(jù)隨機(jī)輸入 reducer备恤,每個(gè)reducer做部分聚合,相同的key就會(huì)分布在不同的reducer中射亏。第二 個(gè)job再將前面預(yù)處理過的數(shù)據(jù)按key聚合并輸出結(jié)果命斧,這樣就起到了均衡的效果田晚。

但是国葬,配置項(xiàng)畢竟是死的汇四,單純靠它有時(shí)不能根本上解決問題,建議了解數(shù)據(jù)傾斜 的細(xì)節(jié),并優(yōu)化查詢語句行剂。

join的在基礎(chǔ)優(yōu)化

hive join 的三種方式

  1. common join

普通連接,在SQL中不特殊指定連接方式使用的都是這種普通連接,兩個(gè)數(shù)據(jù)在做連接之前,會(huì)先去做shuffle撵幽,如下圖,會(huì)將關(guān)聯(lián)id,相同的時(shí)候同一個(gè)區(qū)测垛,再去真正的關(guān)聯(lián)

缺點(diǎn):性能差(性能差的原因:要將數(shù)據(jù)分區(qū),有shuffle)

優(yōu)點(diǎn):操作簡單链快,適應(yīng)性強(qiáng)

common Join.png
  1. map join

map端連接噪猾,與普通連接的區(qū)別是這個(gè)連接中不會(huì)有reduce階段存在,連接在map端完成

適用場(chǎng)景:大表與小表連接,小表數(shù)據(jù)量應(yīng)該能夠完全加載到內(nèi)存贱田,否則不適用

優(yōu)點(diǎn):在大小表連接時(shí)性能提升明顯,

備注:Hive 0.6 的時(shí)候默認(rèn)認(rèn)為寫在select 后面的是大表,前面的是小表帆离, 或者使用 /+mapjoin(map_table) / select a., b. from a join b on a.id = b.id【要求小表在前麻献,大表之后】

hive 0.7 的時(shí)候這個(gè)計(jì)算是自動(dòng)化的监婶,它首先會(huì)自動(dòng)判斷哪個(gè)是小表煮盼,哪個(gè)是大 表,這個(gè)參數(shù)由(hive.auto.convert.join=true)來控制报破,然后控制小表的大小由 (hive.smalltable.filesize=25000000)參數(shù)控制(默認(rèn)是25M),當(dāng)小表超過這個(gè) 大小帆疟,hive 會(huì)默認(rèn)轉(zhuǎn)化成common join妈嘹。

Hive 0.8.1柬脸,hive.smalltable.filesize => hive.mapjoin.smalltable.filesize 缺點(diǎn):使用范圍較小,只針對(duì)大小表且小表能完全加載到內(nèi)存中的情況。

  1. bucket map join

分桶連接:Hive 建表的時(shí)候支持hash 分區(qū)通過指定clustered by (col_name,xxx ) into number_buckets buckets 關(guān)鍵字.當(dāng)連接的兩個(gè)表的join key 就是bucket column 的時(shí)候序愚,就可以通過設(shè)置hive.optimize.bucketmapjoin= true 來執(zhí)行優(yōu) 化精刷。

原理:通過兩個(gè)表分桶在執(zhí)行連接時(shí)會(huì)將小表的每個(gè)分桶映射成hash表锈遥,每個(gè)task 節(jié)點(diǎn)都需要這個(gè)小表的所有hash表,但是在執(zhí)行時(shí)只需要加載該task所持有大表分 桶對(duì)應(yīng)的小表部分的hash表就可以侠驯,所以對(duì)內(nèi)存的要求是能夠加載小表中最大的 hash塊即可儒士。

注意點(diǎn):小表與大表的分桶數(shù)量需要是倍數(shù)關(guān)系,這個(gè)是因?yàn)榉滞安呗詻Q定的檩坚,分桶時(shí)會(huì)根據(jù)分桶字段對(duì)桶數(shù)取余后決定哪個(gè)桶的着撩,所以要保證成倍數(shù)關(guān)系。

優(yōu)點(diǎn):比map join對(duì)內(nèi)存的要求降低匾委,能在逐行對(duì)比時(shí)減少數(shù)據(jù)計(jì)算量(不用比對(duì) 小表全量)

缺點(diǎn):只適用于分桶表

利用map join特性

map join特別適合大小表join的情況拖叙。Hive會(huì)將build table和probe table在map端直接完成join過程,消滅了reduce剩檀,效率很高憋沿。

select a.event_type, b.upload_time from calendar_event_code a
inner join (
  select event_type, upload_time from calendar_record_log
where pt_date = 20190225
) b on a.event_type < b.event_type;

map join的配置項(xiàng)是 hive.auto.convert.join ,默認(rèn)值true沪猴。

當(dāng)build table大小小于hive.mapjoin.smalltable.filesize 會(huì)啟用map join辐啄, 默認(rèn)值25000000(約25MB)。還有 hive.mapjoin.cache.numrows 运嗜,表示緩存 build table的多少行數(shù)據(jù)到內(nèi)存壶辜,默認(rèn)值25000。

分桶表map join

map join對(duì)分桶表還有特別的優(yōu)化担租。由于分桶表是基于一列進(jìn)行hash存儲(chǔ)的砸民,因此 非常適合抽樣(按桶或按塊抽樣)。它對(duì)應(yīng)的配置項(xiàng)是 hive.optimize.bucketmapjoin 。

傾斜均衡配置項(xiàng)

這個(gè)配置與 group by 的傾斜均衡配置項(xiàng)異曲同工岭参,通過 hive.optimize.skewjoin 來配置反惕,默認(rèn)false。如果開啟了演侯,在join過程中Hive會(huì)將計(jì)數(shù)超過閾值 hive.skewjoin.key (默認(rèn) 100000)的傾斜key對(duì)應(yīng)的行臨時(shí)寫進(jìn)文件中姿染,然后再啟動(dòng)另一個(gè)job做map join生 成結(jié)果。通過 hive.skewjoin.mapjoin.map.tasks 參數(shù)還可以控制第二個(gè)job的 mapper數(shù)量秒际,默認(rèn)10000悬赏。

去掉空值和無意義的值

日志類數(shù)據(jù)中往往會(huì)有一些項(xiàng)沒有記錄到,其值為null娄徊,或者空字符串闽颇、-1等。如果 缺失的項(xiàng)很多寄锐,在做join時(shí)這些空值就會(huì)非常集中兵多,拖累進(jìn)度【備注:這個(gè)字段是連接字段】。

若不需要空值數(shù)據(jù)锐峭,就提前寫 where 語句過濾掉中鼠。需要保留的話,將空值key用隨 機(jī)方式打散沿癞,例如將用戶ID為null的記錄隨機(jī)改為負(fù)值:

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;
單獨(dú)處理傾斜的key

如果傾斜的 key 有實(shí)際的意義,一般來講傾斜的key都很少矛渴,此時(shí)可以將它們單獨(dú)抽 取出來椎扬,對(duì)應(yīng)的行單獨(dú)存入臨時(shí)表中,然后打上一個(gè)較小的隨機(jī)數(shù)前綴(比如 0~9)具温,最后再進(jìn)行聚合蚕涤。

不要一個(gè)Select語句中,寫太多的Join铣猩。一定要了解業(yè)務(wù)揖铜,了解數(shù)據(jù)。(A0-A9) 分成多條語句达皿,分步執(zhí)行;(A0-A4; A5-A9);先執(zhí)行大表與小表的關(guān)聯(lián);

調(diào)整Map數(shù)

通常情況下天吓,作業(yè)會(huì)通過輸入數(shù)據(jù)的目錄產(chǎn)生一個(gè)或者多個(gè)map任務(wù)。主要因素包括:

  • 輸入文件總數(shù)
  • 輸入文件大小
  • HDFS文件塊大小

Map不是越多也好峦椰,而是合適的才是最好的龄寞。

如果一個(gè)任務(wù)有很多小文件(遠(yuǎn)遠(yuǎn)小于128M),每個(gè)小文件也會(huì)被當(dāng)做成一個(gè)數(shù)據(jù)塊汤功,用一個(gè)MapTask來完成物邑,一個(gè)MapTask啟動(dòng)和初始化時(shí)間遠(yuǎn)遠(yuǎn)大于處理時(shí)間,就會(huì)造成資源浪費(fèi),而且系統(tǒng)中可用的map是有限的色解。

對(duì)于小文件采用的策略是合并小文件茂嗓。

每個(gè)map處理接近128M的文件塊,會(huì)有其他問題嗎科阎。也不一定述吸。

有一個(gè)125M的文件,一般情況下會(huì)用一個(gè)Map Task完成萧恕。假設(shè)這個(gè)文件字段很 少刚梭,但記錄數(shù)卻非常多。如果Map處理的邏輯比較復(fù)雜票唆,用一個(gè)map任務(wù)去做朴读,性 能也不好。

對(duì)于復(fù)雜文件采用的策略是增加 Map 數(shù)

computeSliteSize(max(minSize, min(maxSize, blocksize))) = blocksize
minSize : mapred.min.split.size (默認(rèn)值1)
maxSize : mapred.max.split.size (默認(rèn)值256M)
調(diào)整maxSize最大值走趋。讓maxSize最大值低于blocksize就可以增加map的個(gè)數(shù)衅金。 建議用set的方式,針對(duì)SQL語句進(jìn)行調(diào)整簿煌。

調(diào)整Reduce數(shù)

reducer數(shù)量的確定方法比mapper簡單得多氮唯。使用參數(shù) mapred.reduce.tasks可以直接設(shè)定reducer數(shù)量。如果未設(shè)置該參數(shù)姨伟,Hive會(huì)進(jìn)行自行推測(cè)惩琉,邏輯如下:

  • 參數(shù)hive.exec.reducers.bytes.per.reducer用來設(shè)定每個(gè)reducer能夠處理的最大數(shù)據(jù)量,默認(rèn)值256M
  • 參數(shù)hive.exec.reducers.max用來設(shè)定每個(gè)job的最大reducer數(shù)量夺荒,默認(rèn)值999(1.2版本之前)或1009(1.2版本之后)
  • 得出reducer數(shù):reducer_num = Min(total_input_size / hive.exec.reducers.bytes.per.reducer,hive.exec.reducers.max )

即: min(輸入總數(shù)據(jù)量 / 256M, 1009)

reducer數(shù)量與輸出文件的數(shù)量相關(guān)瞒渠。如果reducer數(shù)太多,會(huì)產(chǎn)生大量小文件技扼,對(duì) HDFS造成壓力伍玖。如果reducer數(shù)太少,每個(gè)reducer要處理很多數(shù)據(jù)剿吻,容易拖慢運(yùn)行 時(shí)間或者造成OOM窍箍。

Hive優(yōu)化小結(jié)

深入理解 Hadoop 的核心能力,對(duì)Hive優(yōu)化很有幫助丽旅。Hadoop/Hive 處理數(shù)據(jù)過 程椰棘,有幾個(gè)顯著特征:

  • 不怕數(shù)據(jù)多,就怕數(shù)據(jù)傾斜
  • 對(duì)job數(shù)比較多的作業(yè)運(yùn)行效率相對(duì)比較低魔招,比如即使有幾百行的表晰搀,多次關(guān)聯(lián)多次匯總,產(chǎn)品十幾個(gè)jobs办斑,執(zhí)行時(shí)間也需要較長時(shí)間外恕。MapReduce作業(yè)初始化的時(shí)間是比較長的杆逗。
  • 對(duì)sum、count的聚合操作來說鳞疲,不存在數(shù)據(jù)傾斜
  • count(distinct) 效率較低罪郊,數(shù)據(jù)量大容易出問題

從大的方面來說,優(yōu)化可以從幾個(gè)方面

  • 好的設(shè)計(jì)模型尚洽,事半功倍(該分區(qū)分區(qū)悔橄,該分桶分桶,壓縮腺毫、本地模式)
  • 解決數(shù)據(jù)傾斜問題癣疟。僅僅依靠參數(shù)解決數(shù)據(jù)傾斜,是通用的優(yōu)化手段潮酒,收獲有限睛挚。開發(fā)人員應(yīng)該熟悉業(yè)務(wù),了解數(shù)據(jù)規(guī)律急黎,通過業(yè)務(wù)邏輯解決數(shù)據(jù)傾斜往往更可靠扎狱。
  • 減少job數(shù)
  • 設(shè)置合理的mapTask、reduceTask數(shù)
  • 對(duì)小文件進(jìn)行合并
  • 優(yōu)化整體勃教,單一作業(yè)優(yōu)化不如整體優(yōu)化淤击。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市故源,隨后出現(xiàn)的幾起案子污抬,更是在濱河造成了極大的恐慌,老刑警劉巖绳军,帶你破解...
    沈念sama閱讀 210,835評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件壕吹,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡删铃,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,900評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門踏堡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來猎唁,“玉大人,你說我怎么就攤上這事顷蟆〗胗纾” “怎么了?”我有些...
    開封第一講書人閱讀 156,481評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵帐偎,是天一觀的道長逐纬。 經(jīng)常有香客問我,道長削樊,這世上最難降的妖魔是什么豁生? 我笑而不...
    開封第一講書人閱讀 56,303評(píng)論 1 282
  • 正文 為了忘掉前任兔毒,我火速辦了婚禮,結(jié)果婚禮上甸箱,老公的妹妹穿的比我還像新娘育叁。我一直安慰自己,他們只是感情好芍殖,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,375評(píng)論 5 384
  • 文/花漫 我一把揭開白布豪嗽。 她就那樣靜靜地躺著,像睡著了一般豌骏。 火紅的嫁衣襯著肌膚如雪龟梦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,729評(píng)論 1 289
  • 那天窃躲,我揣著相機(jī)與錄音计贰,去河邊找鬼。 笑死框舔,一個(gè)胖子當(dāng)著我的面吹牛蹦玫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播刘绣,決...
    沈念sama閱讀 38,877評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼樱溉,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了纬凤?” 一聲冷哼從身側(cè)響起福贞,我...
    開封第一講書人閱讀 37,633評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎停士,沒想到半個(gè)月后挖帘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,088評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恋技,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,443評(píng)論 2 326
  • 正文 我和宋清朗相戀三年拇舀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜻底。...
    茶點(diǎn)故事閱讀 38,563評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡骄崩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出薄辅,到底是詐尸還是另有隱情要拂,我是刑警寧澤,帶...
    沈念sama閱讀 34,251評(píng)論 4 328
  • 正文 年R本政府宣布站楚,位于F島的核電站脱惰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏窿春。R本人自食惡果不足惜拉一,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,827評(píng)論 3 312
  • 文/蒙蒙 一采盒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧舅踪,春花似錦纽甘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,712評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至货徙,卻和暖如春左权,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背痴颊。 一陣腳步聲響...
    開封第一講書人閱讀 31,943評(píng)論 1 264
  • 我被黑心中介騙來泰國打工赏迟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蠢棱。 一個(gè)月前我還...
    沈念sama閱讀 46,240評(píng)論 2 360
  • 正文 我出身青樓锌杀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親泻仙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子糕再,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,435評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容