Hive優(yōu)化
今天的主要內(nèi)容——Hive優(yōu)化
-
Fetch抓取
- Hive 中對某些情況的查詢可以不必使用 MapReduce 計(jì)算
-
本地模式
- 當(dāng)數(shù)據(jù)量非常小的時(shí)候竞阐,通過設(shè)置本地模式在單臺(tái)機(jī)器上處理所有任務(wù)喘沿,可提高效率
-
表的優(yōu)化
小表join大表
-
大表join大表
空KEY過濾
空Key轉(zhuǎn)化
-
MapJoin
注意:MapJoin的工作機(jī)制
mapjoin對分桶表join的優(yōu)化
-
Group By
- Map端的聚合
-
Count(Distinct) 去重統(tǒng)計(jì)
- 一般 COUNT DISTINCT 使用先 GROUP BY 再 COUNT 的方式替換
-
笛卡爾積
- 避免使用笛卡爾積
-
行列過濾
避免使用select *
通過子查詢后蓖救,再關(guān)聯(lián)表
-
動(dòng)態(tài)分區(qū)的調(diào)整
- 注意動(dòng)態(tài)分區(qū)的語法
-
分桶
- 分桶的理解以及插入數(shù)據(jù)時(shí)注意事項(xiàng)
-
分區(qū)
- 分區(qū)的理解
-
left semi join
- 對 in/exists的子查詢提供了更高效的優(yōu)化方式
insert into 代替 union all
-
數(shù)據(jù)傾斜
合理設(shè)置Map數(shù)量
小文件合并
復(fù)雜文件增加Map數(shù)
合理設(shè)置Reduce數(shù)量
并行執(zhí)行
嚴(yán)格模式
JVM重用(同一個(gè)job中的tasks)
推測執(zhí)行
壓縮
執(zhí)行計(jì)劃
一、Fetch抓取
-
概念:
Fetch 抓取是指旧困,Hive 中對某些情況的查詢可以不必使用 MapReduce 計(jì)算醇份。
-
例如:
SELECT * FROM emp;
在這種情況下,Hive 可以簡單地讀取 emp 對應(yīng)的存儲(chǔ)目錄下的文件吼具,然后輸出查詢結(jié)果到控制臺(tái)僚纷。
-
操作
在 hive-default.xml.template 文件中 hive.fetch.task.conversion屬性值設(shè)置
-
修改屬性值:
-
hive.fetch.task.conversion
CDH5.3.6中對應(yīng)的hive 0.13.1中,該屬性值默認(rèn)為minimal
-
之后新版中該屬性值默認(rèn)為more
* none : disable hive.fetch.task.conversion * minimal : SELECT STAR, FILTER on partition columns, LIMIT only * minimal格式下:只有select * ; filter分區(qū)列過濾 下不走M(jìn)R * more : SELECT, FILTER, LIMIT only (support TABLESAMPLE and virtual columns) * more格式下:select拗盒;filter怖竭;limit不走M(jìn)R
-
二、本地模式(小任務(wù))
-
概念
當(dāng)數(shù)據(jù)量非常小時(shí)陡蝇,在這種情況下痊臭,為查詢觸發(fā)執(zhí)行任務(wù)時(shí)消耗可能會(huì)比實(shí)際 job 的執(zhí)行時(shí)間要多的多哮肚。
-
可以聯(lián)系到hadoop運(yùn)行MapReduce job時(shí)候:
- 當(dāng)job很小時(shí),application master會(huì)在自己的本地虛擬機(jī)中運(yùn)行tasks广匙,這時(shí)相比較于allocating and running in new containers的成本而言的绽左,也就是說相比較于開啟一個(gè)新的container并耗費(fèi)資源拉取數(shù)據(jù)的時(shí)間比job執(zhí)行時(shí)間都長。
-
滿足以下條件時(shí)艇潭,可以使Hive 通過本地模式在單臺(tái)機(jī)器上處理所有的任務(wù)。
job的輸入數(shù)據(jù)大小必須小于參數(shù):hive.exec.mode.local.auto.inputbytes.max(默認(rèn)128MB)
輸入文件的個(gè)數(shù)必須小于參數(shù)hive.exec.mode.local.auto.input.files.max戏蔑,默認(rèn)為4
job的reduce數(shù)必須為0或者1
-
操作
set hive.exec.mode.local.auto=true; //開啟本地 mr
-
set hive.exec.mode.local.auto.inputbytes.max=50000000;
- 設(shè)置 local mr 的最大輸入數(shù)據(jù)量蹋凝,當(dāng)輸入數(shù)據(jù)量小于這個(gè)值時(shí)采用 local mr 的方式,默認(rèn)為 134217728总棵,即 128M
-
set hive.exec.mode.local.auto.input.files.max=10;
- 設(shè)置 local mr 的最大輸入文件個(gè)數(shù)鳍寂,當(dāng)輸入文件個(gè)數(shù)小于這個(gè)值時(shí)采用 local mr 的方式,默認(rèn)為 4
三情龄、表的優(yōu)化
1. 小表join大表
-
概念
-
大表放在后面
hive在處理每一個(gè)MR階段的join時(shí)迄汛,the last table in the sequence is streamed through the reducers whereas the others are buffered。即最后一張表是通過reducer拉取數(shù)據(jù)得到的骤视,而前面的表均是緩存到內(nèi)存中的鞍爱,因此,為了減少reducer內(nèi)存的使用专酗,選擇將數(shù)據(jù)量大的表放在最后邊睹逃,其他表緩存到reducer中)
因此通常需要將小表放前面,或者標(biāo)記哪張表是大表:/*streamtable(table_name) */
將 key 相對分散祷肯,并且數(shù)據(jù)量小的表放在 join 的左邊沉填,這樣可以有效減少內(nèi)存溢出錯(cuò)誤發(fā)生的幾率;再進(jìn)一步佑笋,可以使用 Group 讓小的維度表(1000 條以下的記錄條數(shù))先進(jìn)內(nèi)存翼闹。在 map 端完成 reduce。(也就是開啟map端的聚合)蒋纬、
-
使用相同連接鍵
首先要明白: hive是將joins轉(zhuǎn)化為MR任務(wù)去執(zhí)行的猎荠,當(dāng)多張表的連接條件為同一個(gè)join clause則開啟一個(gè)MR任務(wù),當(dāng)不同的join clauses時(shí)颠锉,則開啟多個(gè)MR任務(wù)法牲。
因此,當(dāng)對3個(gè)或者更多個(gè)表進(jìn)行join連接時(shí)琼掠,如果每個(gè)on子句都使用相同的連接鍵的話拒垃,那么只會(huì)產(chǎn)生一個(gè)MapReduce job。
實(shí)際測試發(fā)現(xiàn):新版的 hive 已經(jīng)對小表 JOIN 大表和大表 JOIN 小表進(jìn)行了優(yōu)化瓷蛙。小表放在左邊和右邊已經(jīng)沒有明顯區(qū)別悼瓮。
其實(shí)開啟map端join后戈毒,還可以避免數(shù)據(jù)傾斜問題
-
-
操作
- 設(shè)置屬性值hive.auto.convert.join,默認(rèn)為true
2. 大表join大表
2.1 空KEY過濾
-
概念
有時(shí) join 超時(shí)是因?yàn)槟承?key 對應(yīng)的數(shù)據(jù)太多横堡,而相同 key 對應(yīng)的數(shù)據(jù)都會(huì)發(fā)送到相同的 reducer 上埋市,從而導(dǎo)致內(nèi)存不夠,
-
此時(shí)我們應(yīng)該仔細(xì)分析這些異常的 key命贴,很多情況下道宅,這些 key 對應(yīng)的數(shù)據(jù)是異常數(shù)據(jù),我們需要在 SQL 語句中進(jìn)行過濾胸蛛。例如 key 對應(yīng)的字段為空
insert overwrite table jointable select n.* from ( select * from nullidtable where id is not null ) n left join ori o on n.id = o.id;
2.2 空KEY轉(zhuǎn)化
-
概念
有時(shí)雖然某個(gè) key 為空對應(yīng)的數(shù)據(jù)很多污茵,但是相應(yīng)的數(shù)據(jù)不是異常數(shù)據(jù),必須要包含在join 的結(jié)果中葬项,此時(shí)我們可以表 a 中 key 為空的字段賦一個(gè)隨機(jī)的值泞当,使得數(shù)據(jù)隨機(jī)均勻地分不到不同的 reducer 上。
此時(shí)注意:空key表full join表民珍,防止數(shù)據(jù)丟失
-
操作
-
設(shè)置reduce個(gè)數(shù)
set mapreduce.job.reduces = 5;
-
join(空KEY轉(zhuǎn)化)
insert overwrite table jointable select n.* from nullidtable n full join ori o on case when n.id is null then concat('hive', rand()) else n.id end = o.id;
-
3. MapJoin
-
概念
如果不指定 MapJoin 或者不符合 MapJoin 的條件襟士,那么 Hive 解析器會(huì)將 Join 操作轉(zhuǎn)換,成 Common Join
即:在 Reduce 階段完成 join嚷量。容易發(fā)生數(shù)據(jù)傾斜陋桂。可以用 MapJoin 把小表全部加載到內(nèi)存在 map 端進(jìn)行 join蝶溶,避免 reducer 處理章喉。
-
參數(shù)設(shè)置
- hive.auto.convert.join 設(shè)置mapjoin打開關(guān)閉;默認(rèn)為true
- hive.mapjoin.smalltable.filesize 設(shè)置小表閾值身坐,默認(rèn)為25000000;25M
-
深入理解
當(dāng)滿足mapjoin條件時(shí)秸脱,會(huì)自動(dòng)更改為mapJoin
也可以手動(dòng)指定為MapJoin
-
But the mapjoin hint should only be used for the following query
if all the inputs are bucketed or sorted,and the join should be converted to a bucketed map-side join or bucketized sort-merge join.
-
當(dāng)兩張join的表根據(jù)同一列進(jìn)行分桶,且表的分桶數(shù)相同或者成倍數(shù)部蛇,則兩表連接時(shí)會(huì)對應(yīng)join
select /* + MAPJOIN(b)*/ a.key,a.value from a join b on a.key = b.key
join can be done on the mapper only
Instead of fetching B completely for each mapper of A,only the required buckets are fetched.
the mapper processing bucket 1 for A will only fetch bucket 1 of B
需要設(shè)置屬性:set hive.optimize.bucketmapjoin = true;
當(dāng)兩張join的表根據(jù)同一列進(jìn)行分桶且桶內(nèi)根據(jù)此列有序摊唇,且表的分桶數(shù)相同,a sort-merge join can be performed. The corresponding buckets are joined with each other at the mapper.
4. Group By
-
概念
默認(rèn)情況下涯鲁,Map 階段同一 Key 數(shù)據(jù)分發(fā)給一個(gè) reduce巷查,當(dāng)一個(gè) key 數(shù)據(jù)過大時(shí)就傾斜了。
并不是所有的聚合操作都需要在 Reduce 端完成抹腿,很多聚合操作都可以先在 Map 端進(jìn)行部分聚合岛请,最后在 Reduce 端得出最終結(jié)果。
可對應(yīng)于hadoop的MapReduce中的combine操作警绩,與reduce實(shí)現(xiàn)相同業(yè)務(wù)邏輯崇败,運(yùn)行每一個(gè)map task中,減輕shuffle中從map到reduce的傳輸。
-
不是所有的聚合都需要進(jìn)行此項(xiàng)優(yōu)化后室。當(dāng)group by 的字段沒有相同的時(shí)缩膝,則無效
select * from emp group by empno;
因?yàn)閑mpno沒有重復(fù)的,因此map聚合沒有太大意義岸霹,并且浪費(fèi)資源疾层。
-
參數(shù)設(shè)置
-
是否在 Map 端進(jìn)行聚合,默認(rèn)為 True
hive.map.aggr = true
-
在 Map 端進(jìn)行聚合操作的條目數(shù)目
hive.groupby.mapaggr.checkinterval = 100000
-
有數(shù)據(jù)傾斜的時(shí)候進(jìn)行負(fù)載均衡(默認(rèn)是 false)
hive.groupby.skewindata = true * 當(dāng)選項(xiàng)設(shè)定為 true贡避,生成的查詢計(jì)劃會(huì)有兩個(gè) MR Job痛黎。 * 第一個(gè) MR Job 中,Map 的輸出結(jié)果會(huì)隨機(jī)分布到 Reduce 中刮吧,每個(gè) Reduce 做部分聚合操作舅逸,并輸出結(jié)果,這樣處理的結(jié)果是相同的 Group By Key 有可能被分發(fā)到不同的 Reduce 中皇筛,從而達(dá)到負(fù)載均衡的目的;坠七、 * 第二個(gè) MR Job 再根據(jù)預(yù)處理的數(shù)據(jù)結(jié)果按照 Group By Key 分布到 Reduce 中(這個(gè)過程可以保證相同的 Group By Key 被分布到同一個(gè) Reduce 中)水醋,最后完成最終的聚合操作。
-
5. count(distinct) 去重統(tǒng)計(jì)
-
概念
數(shù)據(jù)量小的時(shí)候無所謂彪置,數(shù)據(jù)量大的情況下拄踪,由于 COUNT DISTINCT 操作需要用一個(gè)Reduce Task 來完成,這一個(gè) Reduce 需要處理的數(shù)據(jù)量太大拳魁,就會(huì)導(dǎo)致整個(gè) Job 很難完成惶桐,
一般 COUNT DISTINCT 使用先 GROUP BY 再 COUNT 的方式替換:
-
參數(shù)設(shè)置
-
set mapreduce.job.reduces = xxxx; 對reduce個(gè)數(shù)進(jìn)行設(shè)置
select count(id) from ( select id from bigtable group by id) a;
先根據(jù)id進(jìn)行部分聚合,然后統(tǒng)計(jì)個(gè)數(shù)
-
6. 笛卡爾積
* 盡量避免笛卡爾積潘懊,join 的時(shí)候不加 on 條件姚糊,或者無效的 on 條件,Hive 只能使用 1個(gè) reducer 來完成笛卡爾積
7. 行列過濾
-
列處理:
- 在 SELECT 中授舟,只拿需要的列救恨,如果有,盡量使用分區(qū)過濾释树,少用 SELECT *肠槽。
-
行處理:
-
在分區(qū)剪裁中,當(dāng)使用外關(guān)聯(lián)時(shí)奢啥,如果將副表的過濾條件寫在 Where 后面那么就會(huì)先全表關(guān)聯(lián)秸仙,之后再過濾,應(yīng)該通過子查詢后桩盲,再關(guān)聯(lián)表
select b.id from bigtable b join ( select id from ori where id <= 10 ) o on b.id = o.id;
-
8. 動(dòng)態(tài)分區(qū)調(diào)整
-
概念
關(guān)系型數(shù)據(jù)庫中寂纪,對分區(qū)表 Insert 數(shù)據(jù)時(shí)候,數(shù)據(jù)庫自動(dòng)會(huì)根據(jù)分區(qū)字段的值赌结,將數(shù)據(jù)插入到相應(yīng)的分區(qū)中
Hive 中也提供了類似的機(jī)制弊攘,即動(dòng)態(tài)分區(qū)(Dynamic Partition)抢腐,只不過,使用 Hive 的動(dòng)態(tài)分區(qū)襟交,需要進(jìn)行相應(yīng)的配置迈倍。
-
參數(shù)設(shè)置
-
開啟動(dòng)態(tài)分區(qū)功能(默認(rèn) true,開啟)
hive.exec.dynamic.partition=true
-
設(shè)置為非嚴(yán)格模式(動(dòng)態(tài)分區(qū)的模式捣域,默認(rèn) strict啼染,表示必須指定至少一個(gè)分區(qū)為靜態(tài)分區(qū),nonstrict 模式表示允許所有的分區(qū)字段都可以使用動(dòng)態(tài)分區(qū)焕梅。)
hive.exec.dynamic.partition.mode=nonstrict
-
在所有執(zhí)行 MR 的節(jié)點(diǎn)上迹鹅,最大一共可以創(chuàng)建多少個(gè)動(dòng)態(tài)分區(qū)。
hive.exec.max.dynamic.partitions=1000
-
在每個(gè)執(zhí)行 MR 的節(jié)點(diǎn)上贞言,最大可以創(chuàng)建多少個(gè)動(dòng)態(tài)分區(qū)斜棚。該參數(shù)需要根據(jù)實(shí)際的數(shù)據(jù)來設(shè)定。比如:源數(shù)據(jù)中包含了一年的數(shù)據(jù)该窗,即 day 字段有 365 個(gè)值弟蚀,那么該參數(shù)就需要設(shè)置成大于 365,如果使用默認(rèn)值 100酗失,則會(huì)報(bào)錯(cuò)义钉。
hive.exec.max.dynamic.partitions.pernode=100
-
整個(gè) MR Job 中,最大可以創(chuàng)建多少個(gè) HDFS 文件规肴。
hive.exec.max.created.files=100000
-
當(dāng)有空分區(qū)生成時(shí)捶闸,是否拋出異常。一般不需要設(shè)置拖刃。
hive.error.on.empty.partition=false
-
-
操作
insert overwrite table ori_partitioned_target partition (p_time) //指定分區(qū)列 select id, time, uid, keyword, url_rank, click_num, click_url, p_time //分區(qū)列也要作為一個(gè)字段查出 from ori_partitioned;
9. 分區(qū)
-
分區(qū)的理解:
分區(qū)是一種根據(jù)“分區(qū)列”的值對表進(jìn)行粗略劃分的機(jī)制
-
Hive中的每個(gè)分區(qū)對應(yīng)著數(shù)據(jù)庫中相應(yīng)分區(qū)列的一個(gè)索引删壮;
每個(gè)分區(qū)對應(yīng)著表下的一個(gè)目錄
分區(qū)在HDFS上的表現(xiàn)形式與表在 HDFS上的表現(xiàn)形式相同,都是以子目錄的形式存在
-
查詢時(shí)通過where選擇查詢的指定分區(qū)兑牡,可提高查詢效率醉锅。
- 當(dāng)只需要遍歷小范圍內(nèi)的數(shù)據(jù)時(shí)或一定條件下的數(shù)據(jù),可有效減少掃描數(shù)據(jù)的數(shù)量
-
一個(gè)表可在多個(gè)維度上進(jìn)行分區(qū)发绢,且分區(qū)可以嵌套使用硬耍,建表時(shí)通過partitioned by 來創(chuàng)建分區(qū)
partitioned by (year string)
partitioned by (year string,month string)
-
將分區(qū)加載到表內(nèi)之前,需要指定添加分區(qū)列边酒,否則報(bào)錯(cuò)经柴。
此時(shí)聯(lián)系到動(dòng)分區(qū)的調(diào)整
-
動(dòng)態(tài)分區(qū)需要:
①開啟動(dòng)態(tài)分區(qū)
hive.exec.dynamic.partition=true
②設(shè)置為非嚴(yán)格模式
hive.exec.dynamic.partition.mode=nonstrict
partitioned by 子句中的列是表中正式的列(分區(qū)列,通過select * 可查到)墩朦,但是表數(shù)據(jù)中并不包含這些列
10. 分桶
-
分桶的理解
桶為表提供了額外的結(jié)構(gòu)坯认,hive在處理某些查詢時(shí)利用這個(gè)結(jié)構(gòu),能提高查詢效率
桶通過對指定列進(jìn)行哈希計(jì)算來實(shí)現(xiàn)的,通過對哈希值將一個(gè)列名下的數(shù)據(jù)切分為一組桶牛哺,并使每個(gè)桶對應(yīng)于該列名下的存儲(chǔ)文件
建立桶之前陋气,需要設(shè)置hive.enforce.bucketing = true;
-
分區(qū)和分桶其中一個(gè)區(qū)別在于
分區(qū)中的指定列在表數(shù)據(jù)中不存在,即數(shù)據(jù)文件中不存在
分桶中的指定列在表數(shù)據(jù)中存在
向桶中插入數(shù)據(jù)引润,若分為4個(gè)桶巩趁,則在插入數(shù)據(jù)時(shí),對應(yīng)于4個(gè)reduce操作淳附,輸出4個(gè)文件
-
分區(qū)中的分桶
注意分區(qū)中分桶的數(shù)據(jù)插入
-
clustered by (id) sorted by (age) into 4 buckets
- clustered by 和 sorted by 不會(huì)影響數(shù)據(jù)的導(dǎo)入议慰,插入的數(shù)據(jù)若需要排序,則需要手動(dòng)定義
11. left semi join
-
概念
left semi join是對in/exists子查詢提供了更高效的方式
-
下面兩個(gè)語句等價(jià)
select a.key,a.value from a where a.key in( select b.key from B); 等價(jià)于 select a.key,a.value from a left semi join b on (a.key = b.key)
The restrictions of using left semi join are that the right-side join table should only be referened in the join condition, but not in where or select clause etc.(left semi join中右邊的表只能在on 中被引用奴曙,不可在where别凹,select中等使用)
12. insert into 代替 union all
不同表的union all相當(dāng)于multiple inputs,同一個(gè)表的union all洽糟,相當(dāng)map一次輸出多條炉菲。
-
如果union all的部分個(gè)數(shù)大于2,或者每個(gè)union部分?jǐn)?shù)據(jù)量大坤溃,應(yīng)該拆成多個(gè)insert into 語句拍霜,實(shí)際測試過程中,執(zhí)行時(shí)間能提升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 ...;
四浇雹、數(shù)據(jù)傾斜
概述
-
數(shù)據(jù)傾斜表現(xiàn):
- 任務(wù)進(jìn)度長時(shí)間維持在99%(或100%),查看任務(wù)監(jiān)控頁面屿讽,發(fā)現(xiàn)只有少量(1個(gè)或幾個(gè))reduce子任務(wù)未完成昭灵。因?yàn)槠涮幚淼臄?shù)據(jù)量和其他reduce差異過大。
-
數(shù)據(jù)傾斜原因:
key分布不均勻
業(yè)務(wù)數(shù)據(jù)本身的特性
建表時(shí)考慮不周
-
某些SQL語句本身就有數(shù)據(jù)傾斜
關(guān)鍵詞 情形 后果 -----------------|----------------------------------------------|-------------------------------------------------- join 其中一個(gè)表較小伐谈,但是key集中 分發(fā)到某一個(gè)或幾個(gè)Reduce上的數(shù)據(jù)遠(yuǎn)高于平均值 -----------------|----------------------------------------------|------------------------------------------------- join 大表與大表烂完,但是分桶的判斷字段0值或空值過多 這些空值都由一個(gè)reduce處理,非常慢 -----------------|----------------------------------------------|------------------------------------------------ group by group by 維度過小诵棵,某值的數(shù)量過多 處理某值的reduce非常耗時(shí) -----------------|----------------------------------------------|------------------------------------------------- count distinct 某特殊值過多 處理此特殊值reduce耗時(shí) -----------------|----------------------------------------------|-------------------------------------------------
1. 合理設(shè)置map數(shù)量
-
概念
-
通常情況下抠蚣,作業(yè)會(huì)通過 input 的目錄產(chǎn)生一個(gè)或者多個(gè) map 任務(wù)
主要的決定因素有:input 的文件總個(gè)數(shù),input 的文件大小履澳,集群設(shè)置的文件塊大小嘶窄。
-
涉及到split切片機(jī)制
- size = Math.max(minSize,Math.min(maxSize,blockSize));
如果集群性能好的話,可設(shè)置blockSize
開啟map端的聚合
也可以適當(dāng)調(diào)整環(huán)形緩沖區(qū)的大小以提高效率
-
2. 小文件進(jìn)行合并
-
在 map 執(zhí)行前合并小文件距贷,減少 map 數(shù):
CombineHiveInputFormat 具有對小文件進(jìn)行合并的功能(系統(tǒng)默認(rèn)的格式)柄冲。
-
HiveInputFormat 沒有對小文件合并功能。
set hive.input.format= org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
3. 復(fù)雜文件增加 Map 數(shù)
當(dāng) input 的文件都很大忠蝗,任務(wù)邏輯復(fù)雜现横,map 執(zhí)行非常慢的時(shí)候,可以考慮增加 Map數(shù),來使得每個(gè) map 處理的數(shù)據(jù)量減少戒祠,從而提高任務(wù)的執(zhí)行效率骇两。
-
增加 map 的方法為:根據(jù)
computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M 公式
調(diào)整 maxSize 最大值。讓 maxSize 最大值低于 blocksize 就可以增加 map 的個(gè)數(shù)姜盈。
4. 合理設(shè)置 Reduce 數(shù)
4.1 調(diào)整 reduce 個(gè)數(shù)方法一
-
每個(gè) Reduce 處理的數(shù)據(jù)量默認(rèn)是 256MB
hive.exec.reducers.bytes.per.reducer=256000000
-
每個(gè)任務(wù)最大的 reduce 數(shù)低千,默認(rèn)為 1009
hive.exec.reducers.max=1009
-
計(jì)算 reducer 數(shù)的公式
N=min(參數(shù) 2,總輸入數(shù)據(jù)量/參數(shù) 1)
4.2 調(diào)整 reduce 個(gè)數(shù)方法二
-
在 hadoop 的 mapred-default.xml 文件中修改
設(shè)置每個(gè) job 的 Reduce 個(gè)數(shù) set mapreduce.job.reduces = 15;
具體的個(gè)數(shù)需要經(jīng)過測試來得知
五贩据、并行執(zhí)行
-
概念
Hive 會(huì)將一個(gè)查詢轉(zhuǎn)化成一個(gè)或者多個(gè)階段栋操。這樣的階段可以是 MapReduce 階段、抽樣階段饱亮、合并階段矾芙、limit 階段〗希或者 Hive 執(zhí)行過程中可能需要的其他階段剔宪。
默認(rèn)情況下,Hive 一次只會(huì)執(zhí)行一個(gè)階段壹无。
不過葱绒,如果某些階段不是互相依賴,是可以并行執(zhí)行的斗锭。
-
參數(shù)設(shè)置
set hive.exec.parallel=true; //打開任務(wù)并行執(zhí)行 set hive.exec.parallel.thread.number=16; //同一個(gè) sql 允許最大并行度地淀,默認(rèn)為 8。
不過岖是,在共享集群中帮毁,需要注意下,如果 job 中并行階段增多豺撑,那么集群利用率就會(huì)增加烈疚。當(dāng)然,得是在系統(tǒng)資源比較空閑的時(shí)候才有優(yōu)勢聪轿,否則爷肝,沒資源,并行也起不來
六陆错、嚴(yán)格模式
開啟嚴(yán)格模式可以禁止 3 種類型的查詢灯抛。
1. 分區(qū)表——where過濾
對于分區(qū)表,除非 where 語句中含有分區(qū)字段過濾條件來限制范圍音瓷,否則不允許執(zhí)行牧愁。
就是用戶不允許掃描所有分區(qū)。進(jìn)行這個(gè)限制的原因是外莲,通常分區(qū)表都擁有非常大的數(shù)據(jù)集猪半,而且數(shù)據(jù)增加迅速兔朦。沒有進(jìn)行分區(qū)限制的查詢可能會(huì)消耗令人不可接受的巨大資源來處理這個(gè)表。
2. order by 搭配limit使用
對于使用了 order by 語句的查詢磨确,要求必須使用 limit 語句沽甥。
因?yàn)?order by 為了執(zhí)行排序過程會(huì)將所有的結(jié)果數(shù)據(jù)分發(fā)到同一個(gè) Reducer 中進(jìn)行處理,強(qiáng)制要求用戶增加這個(gè) LIMIT語句可以防止 Reducer 額外執(zhí)行很長一段時(shí)間乏奥。
3. 限制笛卡爾積的查詢摆舟。
- 多表join時(shí),指定join條件
七邓了、JVM重用(針對同一個(gè)job的tasks而言的)
-
概念
JVM 重用是 Hadoop 調(diào)優(yōu)參數(shù)的內(nèi)容恨诱,其對 Hive 的性能具有非常大的影響,特別是對于很難避免小文件的場景或 task 特別多的場景骗炉,這類場景大多數(shù)執(zhí)行時(shí)間都很短照宝。
Hadoop中有個(gè)參數(shù)是mapred.job.reuse.jvm.num.tasks,默認(rèn)是1句葵,表示一個(gè)JVM上最多可以順序執(zhí)行的task數(shù)目(屬于同一個(gè)Job)是1厕鹃。也就是說一個(gè)task啟一個(gè)JVM。
為每個(gè)task啟動(dòng)一個(gè)新的JVM將耗時(shí)1秒左右乍丈,對于運(yùn)行時(shí)間較長(比如1分鐘以上)的job影響不大剂碴,但如果都是時(shí)間很短的task,那么頻繁啟停JVM會(huì)有開銷轻专。
-
參數(shù)設(shè)置
如果我們想使用JVM重用技術(shù)來提高性能忆矛,那么可以將mapred.job.reuse.jvm.num.tasks設(shè)置成大于1的數(shù)。這表示屬于同一job的順序執(zhí)行的task可以共享一個(gè)JVM请垛,也就是說第二輪的map可以重用前一輪的JVM催训,而不是第一輪結(jié)束后關(guān)閉JVM,第二輪再啟動(dòng)新的JVM叼屠。
-
那么最多一個(gè)JVM能順序執(zhí)行多少個(gè)task才關(guān)閉呢瞳腌?
- 這個(gè)值就是mapred.job.reuse.jvm.num.tasks绞铃。如果設(shè)置成-1镜雨,那么只要是同一個(gè)job的task(無所謂多少個(gè)),都可以按順序在一個(gè)JVM上連續(xù)執(zhí)行
如果task屬于不同的job儿捧,那么JVM重用機(jī)制無效荚坞,不同job的task需要不同的JVM來運(yùn)行
-
注意事項(xiàng)
JVM重用技術(shù)不是指同一Job的兩個(gè)或兩個(gè)以上的task可以同時(shí)運(yùn)行于同一JVM上,而是排隊(duì)按順序執(zhí)行菲盾。
一個(gè)tasktracker最多可以同時(shí)運(yùn)行的task數(shù)目由mapred.tasktracker.map.tasks.maximum和mapred.tasktracker.reduce.tasks.maximum決定颓影,并且這兩個(gè)參數(shù)在mapred-site.xml中設(shè)置。
其他方法懒鉴,如在JobClient端通過命令行-Dmapred.tasktracker.map.tasks.maximum=number或者conf.set("mapred.tasktracker.map.tasks.maximum","number")設(shè)置都是無效的诡挂。
這個(gè)功能的缺點(diǎn)是碎浇,開啟 JVM 重用將一直占用使用到的 task 插槽,以便進(jìn)行重用璃俗,直到任務(wù)完成后才能釋放奴璃。如果某個(gè)“不平衡的”job 中有某幾個(gè) reduce task 執(zhí)行的時(shí)間要比其他 Reduce task 消耗的時(shí)間多的多的話,那么保留的插槽就會(huì)一直空閑著卻無法被其他的 job使用城豁,直到所有的 task 都結(jié)束了才會(huì)釋放苟穆。
八、推測執(zhí)行
-
概念
在分布式集群環(huán)境下唱星,因?yàn)槌绦?Bug(包括 Hadoop 本身的 bug)雳旅,負(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 采用了推測執(zhí)行(Speculative Execution)機(jī)制,它根據(jù)一定的法則推測出“拖后腿”的任務(wù)叹话,并為這樣的任務(wù)啟動(dòng)一個(gè)備份任務(wù)偷遗,讓該任務(wù)與原始任務(wù)同時(shí)處理同一份數(shù)據(jù),并最終選用最先成功運(yùn)行完成任務(wù)的計(jì)算結(jié)果作為最終結(jié)果驼壶。
-
參數(shù)設(shè)置
<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> <property> <name>hive.mapred.reduce.tasks.speculative.execution</name> <value>true</value> <description>Whether speculative execution for reducers should be turned on.</description> </property>
-
注意事項(xiàng)
- 如果用戶因?yàn)檩斎霐?shù)據(jù)量很大而需要執(zhí)行長時(shí)間的 map 或者 Reduce task 的話氏豌,那么啟動(dòng)推測執(zhí)行造成的浪費(fèi)是非常巨大大。