真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Hive的調(diào)優(yōu)有哪些

小編給大家分享一下Hive的調(diào)優(yōu)有哪些,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

成都創(chuàng)新互聯(lián)公司長期為1000+客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺(tái),與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為金秀企業(yè)提供專業(yè)的成都做網(wǎng)站、成都網(wǎng)站制作,金秀網(wǎng)站改版等技術(shù)服務(wù)。擁有10多年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。

一、Fetch抓?。℉ive可以避免進(jìn)行MapReduce)

         Hive中對某些情況的查詢可以不必使用MapReduce計(jì)算。例如:SELECT * FROM employees;在這種情況下,Hive可以簡單地讀取employee對應(yīng)的存儲(chǔ)目錄下的文件,然后輸出查詢結(jié)果到控制臺(tái)。
         在hive-default.xml.template文件中hive.fetch.task.conversion默認(rèn)是more,老版本hive默認(rèn)是minimal,該屬性修改為more以后,在全局查找、字段查找、limit查找等都不走mapreduce。

hive.fetch.task.conversionmore  Expects one of [none, minimal, more].
      Some select queries can be converted to single FETCH task minimizing latency.
      Currently the query should be single sourced not having any subquery and should not have
      any aggregations or distincts (which incurs RS), lateral views and joins.
      0. none : disable hive.fetch.task.conversion
  

1.1 案例實(shí)操

  1. 把hive.fetch.task.conversion設(shè)置成none,然后執(zhí)行查詢語句,都會(huì)執(zhí)行mapreduce程序。

hive (default)> set hive.fetch.task.conversion=none;hive (default)> select * from score;hive (default)> select s_score from score;hive (default)> select s_score from score limit 3;
  1. 把hive.fetch.task.conversion設(shè)置成more,然后執(zhí)行查詢語句,如下查詢方式都不會(huì)執(zhí)行mapreduce程序

1.2 本地模式

         大多數(shù)的Hadoop Job是需要Hadoop提供的完整的可擴(kuò)展性來處理大數(shù)據(jù)集的。不過,有時(shí)Hive的輸入數(shù)據(jù)量是非常小的。在這種情況下,為查詢觸發(fā)執(zhí)行任務(wù)時(shí)消耗可能會(huì)比實(shí)際job的執(zhí)行時(shí)間要多的多。對于大多數(shù)這種情況,Hive可以通過本地模式在單臺(tái)機(jī)器上處理所有的任務(wù)。對于小數(shù)據(jù)集,使用本地模式執(zhí)行時(shí)間可以明顯被縮短。
         用戶可以通過設(shè)置hive.exec.mode.local.auto的值為true,來讓Hive在適當(dāng)?shù)臅r(shí)候自動(dòng)啟動(dòng)這個(gè)優(yōu)化。

set hive.exec.mode.local.auto=true;  --開啟本地MapReduce-- 設(shè)置local mr的最大輸入數(shù)據(jù)量,當(dāng)輸入數(shù)據(jù)量小于這個(gè)值時(shí)采用local mr的方式,默認(rèn)為134217728,即128Mset hive.exec.mode.local.auto.inputbytes.max=51234560;-- 設(shè)置local mr的最大輸入文件個(gè)數(shù),當(dāng)輸入文件個(gè)數(shù)小于這個(gè)值時(shí)采用local mr的方式,默認(rèn)為4set hive.exec.mode.local.auto.input.files.max=10

實(shí)操案例
開啟本地模式,并執(zhí)行查詢語句

hive (default)> set hive.exec.mode.local.auto=true; hive (default)> select * from score cluster by s_id;1.568 seconds

關(guān)閉本地模式,并執(zhí)行查詢語句

hive (default)> set hive.exec.mode.local.auto=false; hive (default)> select * from score cluster by s_id;11.865 seconds

二、group By

         默認(rèn)情況下,Map階段同一Key數(shù)據(jù)分發(fā)給一個(gè)reduce,當(dāng)一個(gè)key數(shù)據(jù)過大時(shí)就傾斜了
         并不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端進(jìn)行部分聚合,最后在Reduce端得出最終結(jié)果。

開啟Map端聚合參數(shù)設(shè)置

-- 是否在Map端進(jìn)行聚合,默認(rèn)為Trueset hive.map.aggr = true;--在Map端進(jìn)行聚合操作的條目數(shù)目set hive.groupby.mapaggr.checkinterval = 100000;-- 有數(shù)據(jù)傾斜的時(shí)候進(jìn)行負(fù)載均衡(默認(rèn)是false)set 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中),最后完成最終的聚合操作。

三、Count(distinct)

         數(shù)據(jù)量小的時(shí)候無所謂,數(shù)據(jù)量大的情況下,由于COUNT DISTINCT操作需要用一個(gè)Reduce Task來完成,這一個(gè)Reduce需要處理的數(shù)據(jù)量太大,就會(huì)導(dǎo)致整個(gè)Job很難完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替換

環(huán)境準(zhǔn)備

create table bigtable(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';load data local inpath '/home/bigtable' into table bigtable;

使用count(distinct)

set hive.exec.reducers.bytes.per.reducer=32123456;SELECT count(DISTINCT id) FROM bigtable;結(jié)果:
c010000Time taken: 35.49 seconds, Fetched: 1 row(s)

使用轉(zhuǎn)換

set hive.exec.reducers.bytes.per.reducer=32123456;SELECT count(id) FROM (SELECT id FROM bigtable GROUP BY id) a;結(jié)果:
Stage-Stage-1: Map: 1  Reduce: 4   Cumulative CPU: 13.07 sec   HDFS Read: 120749896 HDFS Write: 464 SUCCESS
Stage-Stage-2: Map: 3  Reduce: 1   Cumulative CPU: 5.14 sec   HDFS Read: 8987 HDFS Write: 7 SUCCESS
_c010000Time taken: 51.202 seconds, Fetched: 1 row(s)

雖然會(huì)多用一個(gè)Job來完成,但在數(shù)據(jù)量大的情況下,這個(gè)絕對是值得的。

測試數(shù)據(jù)下載 鏈接:https://pan.baidu.com/s/1LwKKJTeXR4h0iaOAknZ7_g 提取碼:5252

四、笛卡爾積

         盡量避免笛卡爾積,即避免join的時(shí)候不加on條件,或者無效的on條件,Hive只能使用1個(gè)reducer來完成笛卡爾積。

五、使用分區(qū)剪裁、列剪裁

         在SELECT中,只拿需要的列,如果有,盡量使用分區(qū)過濾,少用SELECT *。
         在分區(qū)剪裁中,當(dāng)使用外關(guān)聯(lián)時(shí),如果將副表的過濾條件寫在Where后面,那么就會(huì)先全表關(guān)聯(lián),之后再過濾,比如:

數(shù)據(jù)準(zhǔn)備

create table ori(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';create table bigtable(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';load data local inpath '/home/bigtable' into table bigtable;load data local inpath '/home/ori' into table ori;

先關(guān)聯(lián)在Where

select a.id FROM bigtable a left join ori o on a.id=o.id where o.id<=10;

正確寫法是在ON后面: 向Where 在關(guān)聯(lián)

select a.id FROM bigtable a left join ori o  on (o.id<=10 and a.id=o.id);

或者直接寫成子查詢

select a.id from bigtable a join (select  id from ori o where o.id<=10) o on o.id=a.id;

測試數(shù)據(jù)下載 鏈接:https://pan.baidu.com/s/1LwKKJTeXR4h0iaOAknZ7_g 提取碼:5252

六、 動(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)的配置。
         以第一個(gè)表的分區(qū)規(guī)則,來對應(yīng)第二個(gè)表的分區(qū)規(guī)則,將第一個(gè)表的所有分區(qū),全部拷貝到第二個(gè)表中來,第二個(gè)表在加載數(shù)據(jù)的時(shí)候,不需要指定分區(qū)了,直接用第一個(gè)表的分區(qū)即可。
開啟動(dòng)態(tài)分區(qū)參數(shù)設(shè)置

  1. 開啟動(dòng)態(tài)分區(qū)參數(shù)設(shè)置

set hive.exec.dynamic.partition=true;
  1. 設(shè)置為非嚴(yán)格模式(動(dòng)態(tài)分區(qū)的模式,默認(rèn)strict,表示必須指定至少一個(gè)分區(qū)為靜態(tài)分區(qū),nonstrict模式表示允許所有的分區(qū)字段都可以使用動(dòng)態(tài)分區(qū)。)

set hive.exec.dynamic.partition.mode=nonstrict;
  1. 在所有執(zhí)行MR的節(jié)點(diǎn)上,最大一共可以創(chuàng)建多少個(gè)動(dòng)態(tài)分區(qū)。

set  hive.exec.max.dynamic.partitions=1000;
  1. 在每個(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ò)。

set hive.exec.max.dynamic.partitions.pernode=100
  1. 整個(gè)MR Job中,最大可以創(chuàng)建多少個(gè)HDFS文件。
             在linux系統(tǒng)當(dāng)中,每個(gè)linux用戶最多可以開啟1024個(gè)進(jìn)程,每一個(gè)進(jìn)程最多可以打開2048個(gè)文件,即持有2048個(gè)文件句柄,下面這個(gè)值越大,就可以打開文件句柄越大

set hive.exec.max.created.files=100000
  1. 當(dāng)有空分區(qū)生成時(shí),是否拋出異常。一般不需要設(shè)置。

set hive.error.on.empty.partition=false

案例實(shí)操

需求: 將ori中的數(shù)據(jù)按照時(shí)間(如:20111231234568),插入到目標(biāo)表ori_partitioned的相應(yīng)分區(qū)中。

  1. 準(zhǔn)備數(shù)據(jù)表

create table ori_partitioned(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string)PARTITIONED BY (p_time bigint)row format delimited fields terminated by '\t';load data local inpath '/home/small_data' into  table ori_partitioned partition (p_time='20111230000010');load data local inpath '/home/small_data' into  table ori_partitioned partition (p_time='20111230000011');
  1. 創(chuàng)建分區(qū)表

create table ori_partitioned_target(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) PARTITIONED BY (p_time STRING) row format delimited fields terminated by '\t';
  1. 分析
             如果按照之前介紹的往指定一個(gè)分區(qū)中Insert數(shù)據(jù),那么這個(gè)需求很不容易實(shí)現(xiàn)。這時(shí)候就需要使用動(dòng)態(tài)分區(qū)來實(shí)現(xiàn)

set hive.exec.dynamic.partition = true;set hive.exec.dynamic.partition.mode = nonstrict;set hive.exec.max.dynamic.partitions = 1000;set hive.exec.max.dynamic.partitions.pernode = 100;set hive.exec.max.created.files = 100000;set hive.error.on.empty.partition = false;INSERT overwrite TABLE ori_partitioned_target PARTITION (p_time) SELECT id,`time`, uid, keyword, url_rank, click_num, click_url, p_time FROM ori_partitioned;

         注意:在PARTITION (p_time)中指定分區(qū)字段名即可;在SELECT子句的最后幾個(gè)字段,必須對應(yīng)前面PARTITION (p_time)中指定的分區(qū)字段,包括順序。

查看分區(qū)

hive (default)>  show partitions ori_partitioned_target;OKpartitionp_time=20111230000010p_time=20111230000011Time taken: 0.607 seconds, Fetched: 2 row(s)

測試數(shù)據(jù)下載 鏈接:https://pan.baidu.com/s/1LwKKJTeXR4h0iaOAknZ7_g 提取碼:5252

七、數(shù)據(jù)傾斜

7.1 Map數(shù)

         通常情況下,作業(yè)會(huì)通過input的目錄產(chǎn)生一個(gè)或者多個(gè)map任務(wù)
         主要的決定因素有:input的文件總個(gè)數(shù),input的文件大小,集群設(shè)置的文件塊大小(目前為128M,可在hive中通過set dfs.block.size;命令查看到,該參數(shù)不能自定義修改)。

舉例:

  • 一個(gè)大文件:假設(shè)input目錄下有1個(gè)文件a,大小為780M,那么hadoop會(huì)將該文件a分隔成7個(gè)塊6個(gè)128m的塊和1個(gè)12m的塊),從而產(chǎn)生7個(gè)map數(shù)。

  • 多個(gè)小文件:假設(shè)input目錄下有3個(gè)文件a,b,c大小分別為10m,20m,150m,那么hadoop會(huì)分隔成4個(gè)塊10m,20m,128m,22m),從而產(chǎn)生4個(gè)map數(shù)。即,如果文件大于塊大小(128m),那么會(huì)拆分,如果小于塊大小,則把該文件當(dāng)成一個(gè)塊。

  • 是不是map數(shù)越多越好?答案是否定的。如果一個(gè)任務(wù)有很多小文件(遠(yuǎn)遠(yuǎn)小于塊大小128m),則每個(gè)小文件也會(huì)被當(dāng)做一個(gè)塊,用一個(gè)map任務(wù)來完成,而一個(gè)map任務(wù)啟動(dòng)和初始化的時(shí)間遠(yuǎn)遠(yuǎn)大于邏輯處理的時(shí)間,就會(huì)造成很大的資源浪費(fèi)。而且,同時(shí)可執(zhí)行的map數(shù)是受限的。

  • 是不是保證每個(gè)map處理接近128m的文件塊,就高枕無憂了?答案也是不一定。比如有一個(gè)127m的文件,正常會(huì)用一個(gè)map去完成,但這個(gè)文件只有一個(gè)或者兩個(gè)字段,卻有幾千萬的記錄,如果map處理的邏輯比較復(fù)雜,用一個(gè)map任務(wù)去做,肯定也比較耗時(shí)

  • 小結(jié): 針對上面的問題3和4,我們需要采取兩種方式來解決:即減少map數(shù)和增加map數(shù);這個(gè)就看看真實(shí)的場景去確認(rèn)map的數(shù)量。

7.2 如何適當(dāng)?shù)脑黾觤ap數(shù)

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

針對上面的第4條

假設(shè)有這樣一個(gè)任務(wù):

Select data_desc,count(1),count(distinct id),sum(case when …),sum(case when …),sum(…)from a group by data_desc

         如果表a只有一個(gè)文件,大小為120M,但包含幾千萬的記錄,如果用1個(gè)map去完成這個(gè)任務(wù),肯定是比較耗時(shí)的,這種情況下,我們要考慮將這一個(gè)文件合理的拆分成多個(gè),這樣就可以用多個(gè)map任務(wù)去完成。

set mapreduce.job.reduces =10;create table a_1 asselect * from a
distribute by rand();

         這樣會(huì)將a表的記錄,隨機(jī)的分散到包含10個(gè)文件的a_1表中,再用a_1代替上面sql中的a表,則會(huì)用10個(gè)map任務(wù)去完成。
         每個(gè)map任務(wù)處理大于12M(幾百萬記錄)的數(shù)據(jù),效率肯定會(huì)好很多。
         看上去,貌似這兩種有些矛盾,一個(gè)是要合并小文件,一個(gè)是要把大文件拆成小文件,這點(diǎn)正是重點(diǎn)需要關(guān)注的地方,根據(jù)實(shí)際情況,控制map數(shù)量需要遵循兩個(gè)原則:使大數(shù)據(jù)量利用合適的map數(shù);使單個(gè)map任務(wù)處理合適的數(shù)據(jù)量;

7.3 reduce數(shù)

調(diào)整reduce個(gè)數(shù)方法一

  • 每個(gè)Reduce處理的數(shù)據(jù)量默認(rèn)是256MB

hive.exec.reducers.bytes.per.reducer=256123456
  • 計(jì)算reducer數(shù)的公式

hive.exec.reducers.max=1009

調(diào)整reduce個(gè)數(shù)方法二

  • 設(shè)置每個(gè)job的Reduce個(gè)數(shù)

set mapreduce.job.reduces = 15;

reduce個(gè)數(shù)并不是越多越好

  • 過多的啟動(dòng)和初始化reduce也會(huì)消耗時(shí)間和資源;

  • 另外,有多少個(gè)reduce,就會(huì)有多少個(gè)輸出文件,如果生成了很多個(gè)小文件,那么如果這些小文件作為下一個(gè)任務(wù)的輸入,則也會(huì)出現(xiàn)小文件過多的問題;

         在設(shè)置reduce個(gè)數(shù)的時(shí)候也需要考慮這兩個(gè)原則:處理大數(shù)據(jù)量利用合適的reduce數(shù);使單個(gè)reduce任務(wù)處理數(shù)據(jù)量大小要合適;

八、并行執(zhí)行

         Hive會(huì)將一個(gè)查詢轉(zhuǎn)化成一個(gè)或者多個(gè)階段。這樣的階段可以使MapReduce階段、抽樣階段、合并階段、limit階段?;蛘逪ive執(zhí)行過程中可能需要的其他階段。默認(rèn)情況下,Hive一次只會(huì)執(zhí)行一個(gè)階段。不過,某個(gè)特定的job可能包含眾多的階段,而這些階段可能并非完全互相依賴的,也就是說有些階段是可以并行執(zhí)行的,這樣可能使得整個(gè)job的執(zhí)行時(shí)間縮短。不過,如果有更多的階段可以并行執(zhí)行,那么job可能就越快完成。
         通過設(shè)置參數(shù)hive.exec.parallel值為true,就可以開啟并發(fā)執(zhí)行。不過,在共享集群中,需要注意下,如果job中并行階段增多,那么集群利用率就會(huì)增加。

set hive.exec.parallel=true;     //打開任務(wù)并行執(zhí)行set hive.exec.parallel.thread.number=16; //同一個(gè)sql允許最大并行度,默認(rèn)為8。

         當(dāng)然,得是在系統(tǒng)資源比較空閑的時(shí)候才有優(yōu)勢,否則,沒資源,并行也起不來。

九、嚴(yán)格模式

         Hive提供了一個(gè)嚴(yán)格模式,可以防止用戶執(zhí)行“高?!钡牟樵?/code>。
         通過設(shè)置屬性hive.mapred.mode值為默認(rèn)是非嚴(yán)格模式nonstrict 。開啟嚴(yán)格模式需要修改hive.mapred.mode值為strict,開啟嚴(yán)格模式可以禁止3種類型的查詢。

hive.mapred.modestrict  The mode in which the Hive operations are being performed. 
      In strict mode, some risky queries are not allowed to run. They include:
        Cartesian Product.
        No partition being picked up for a query.
        Comparing bigints and strings.
        Comparing bigints and doubles.
        Orderby without limit.
  
  1. 對于分區(qū)表,用戶不允許掃描所有分區(qū),除非where語句中含有分區(qū)字段過濾條件來限制范圍,否則不允許執(zhí)行。進(jìn)行這個(gè)限制的原因是,通常分區(qū)表都擁有非常大的數(shù)據(jù)集,而且數(shù)據(jù)增加迅速。沒有進(jìn)行分區(qū)限制的查詢可能會(huì)消耗令人不可接受的巨大資源來處理這個(gè)表。

  2. 對于使用了order by語句的查詢,要求必須使用limit語句。因?yàn)閛rder by為了執(zhí)行排序過程會(huì)將所有的結(jié)果數(shù)據(jù)分發(fā)到同一個(gè)Reducer中進(jìn)行處理,強(qiáng)制要求用戶增加這個(gè)LIMIT語句可以防止Reducer額外執(zhí)行很長一段時(shí)間

  3. 限制笛卡爾積的查詢。對關(guān)系型數(shù)據(jù)庫非常了解的用戶可能期望在執(zhí)行JOIN查詢的時(shí)候不使用ON語句而是使用where語句這樣關(guān)系數(shù)據(jù)庫的執(zhí)行優(yōu)化器就可以高效地將WHERE語句轉(zhuǎn)化成那個(gè)ON語句。\不幸的是,Hive并不會(huì)執(zhí)行這種優(yōu)化,因此,如果表足夠大,那么這個(gè)查詢就會(huì)出現(xiàn)不可控的情況。

十、 JVM重用

         JVM重用是Hadoop調(diào)優(yōu)參數(shù)的內(nèi)容,其對Hive的性能具有非常大的影響,特別是對于很難避免小文件的場景或task特別多的場景,這類場景大多數(shù)執(zhí)行時(shí)間都很短。
         Hadoop的默認(rèn)配置通常是使用派生JVM來執(zhí)行map和Reduce任務(wù)的。這時(shí)JVM的啟動(dòng)過程可能會(huì)造成相當(dāng)大的開銷,尤其是執(zhí)行的job包含有成百上千task任務(wù)的情況。JVM重用可以使得JVM實(shí)例在同一個(gè)job中重新使用N次。N的值可以在Hadoop的mapred-site.xml文件中進(jìn)行配置。通常在10-20之間,具體多少需要根據(jù)具體業(yè)務(wù)場景測試得出。


  mapreduce.job.jvm.numtasks
  10
  How many tasks to run per jvm. If set to -1, there is
  no limit. 
  

         我們也可以在hive當(dāng)中通過

set  mapred.job.reuse.jvm.num.tasks=10;

         這個(gè)設(shè)置來設(shè)置我們的jvm重用

         這個(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)槌绦駼ug(包括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é)果。
Hive 同樣可以開啟推測執(zhí)行
設(shè)置開啟推測執(zhí)行參數(shù):Hadoop的mapred-site.xml文件中進(jìn)行配置


  mapreduce.map.speculative
  true
  If true, then multiple instances of some map tasks  may be executed in parallel.
  mapreduce.reduce.speculative
  true
  If true, then multiple instances of some reduce tasks   may be executed in parallel.

不過hive本身也提供了配置項(xiàng)來控制reduce-side的推測執(zhí)行:

hive.mapred.reduce.tasks.speculative.executiontrueWhether speculative execution for reducers should be turned on. 
  

         關(guān)于調(diào)優(yōu)這些推測執(zhí)行變量,還很難給一個(gè)具體的建議。如果用戶對于運(yùn)行時(shí)的偏差非常敏感的話,那么可以將這些功能關(guān)閉掉。如果用戶因?yàn)檩斎霐?shù)據(jù)量很大而需要執(zhí)行長時(shí)間的map或者Reduce task的話,那么啟動(dòng)推測執(zhí)行造成的浪費(fèi)是非常巨大大。

十二、表的優(yōu)化

12.1 Join

Join 原則

  1. 小表Join大表
             將key相對分散,并且數(shù)據(jù)量小的表放在join的左邊,這樣可以有效減少內(nèi)存溢出錯(cuò)誤發(fā)生的幾率;再進(jìn)一步,可以使用Group讓小的維度表(1000條以下的記錄條數(shù))先進(jìn)內(nèi)存。在map端完成reduce。

select  count(distinct s_id)  from score;select count(s_id) from score group by s_id; -- 在map端進(jìn)行聚合,效率更高x`
  1. 多個(gè)表關(guān)聯(lián)時(shí),最好分拆成小段,避免大sql(無法控制中間Job)

  2. 大表Join大表
    (1) 空KEY過濾

         有時(shí)join超時(shí)是因?yàn)槟承﹌ey對應(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)的字段為空,操作如下:

create table ori(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';create table nullidtable(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';create table jointable(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';load data local inpath '/home/hive_big_table/*' into table ori;load data local inpath '/home/hive_have_null_id/*' into table nullidtable;

不過濾運(yùn)行結(jié)果

INSERT OVERWRITE TABLE jointable SELECT a.* FROM nullidtable a JOIN ori b ON a.id = b.id;Time taken: 129.416 seconds

過濾運(yùn)行結(jié)果

INSERT OVERWRITE TABLE jointable SELECT a.* FROM (SELECT * FROM nullidtable WHERE id IS NOT NULL ) a JOIN ori b ON a.id = b.id;Time taken: 116.691 seconds

         (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上。例如:
         不隨機(jī)分布:

set hive.exec.reducers.bytes.per.reducer=32123456;set mapreduce.job.reduces=7;INSERT OVERWRITE TABLE jointable SELECT a.* FROM nullidtable a LEFT JOIN ori b ON  CASE WHEN  a.id IS NULL  THEN 'hive'  ELSE a.id  END;Time taken: 42.594  seconds

         結(jié)果:這樣的后果就是所有為null值的id全部都變成了相同的字符串“hive”,及其容易造成數(shù)據(jù)的傾斜(所有的key相同,相同key的數(shù)據(jù)會(huì)到同一個(gè)reduce當(dāng)中去)

         為了解決這種情況,我們可以通過hive的rand函數(shù),隨記的給每一個(gè)為空的id賦上一個(gè)隨機(jī)值,這樣就不會(huì)造成數(shù)據(jù)傾斜
隨機(jī)分布:

set hive.exec.reducers.bytes.per.reducer=32123456;set mapreduce.job.reduces=7;INSERT OVERWRITE TABLE jointable SELECT a.* FROM nullidtable a LEFT JOIN ori b ON  CASE WHEN  a.id IS NULL  THEN concat('hive',rand())  ELSE a.id  END;Time taken: 42.594  seconds

案例實(shí)操
需求:測試大表JOIN小表和小表JOIN大表的效率 (新的版本當(dāng)中已經(jīng)沒有區(qū)別了,舊的版本當(dāng)中需要使用小表

  1. 建大表、小表和JOIN后表的語句

create table bigtable(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';create table smalltable(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';create table jointable2(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';
  1. 分別向大表小表導(dǎo)入數(shù)據(jù)

load data local inpath '/home/bigtable' into table bigtable;
 load data local inpath '/home/small_data' into table smalltable;
  1. 關(guān)閉mapjoin功能(默認(rèn)是打開的)

set hive.auto.convert.join = false;
  1. 執(zhí)行小表JOIN大表語句

INSERT OVERWRITE TABLE jointable2SELECT b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_urlFROM smalltable sleft JOIN bigtable  bON b.id = s.id;Time taken: 30.133 seconds
  1. 執(zhí)行大表JOIN小表語句

INSERT OVERWRITE TABLE jointable2SELECT b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_urlFROM bigtable  bleft JOIN smalltable  sON s.id = b.id;OK
b.id    b.time  b.uid   b.keyword       b.url_rank      b.click_num     b.click_urlTime taken: 25.116 seconds

         可以看出大表join小表或者小表join大表,就算是關(guān)閉map端join的情況下,在新的版本當(dāng)中基本上沒有區(qū)別了(hive為了解決數(shù)據(jù)傾斜的問題,會(huì)自動(dòng)進(jìn)行過濾)

12.2 MapJoin

         如果不指定MapJoin或者不符合MapJoin的條件,那么Hive解析器會(huì)將Join操作轉(zhuǎn)換成Common Join(在Reduce階段完成join)。容易發(fā)生數(shù)據(jù)傾斜。可以用MapJoin把小表全部加載到內(nèi)存在map端進(jìn)行join,避免reducer處理。

開啟MapJoin參數(shù)設(shè)置:

  1. 設(shè)置自動(dòng)選擇Mapjoin

set hive.auto.convert.join = true; 默認(rèn)為true
  1. 大表小表的閾值設(shè)置(默認(rèn)25M以下認(rèn)為是小表):

set hive.mapjoin.smalltable.filesize=25123456;

MapJoin工作機(jī)制

         首先是Task A,它是一個(gè)Local Task(在客戶端本地執(zhí)行的Task),負(fù)責(zé)掃描小表b的數(shù)據(jù),將其轉(zhuǎn)換成一個(gè)HashTable的數(shù)據(jù)結(jié)構(gòu),并寫入本地的文件中,之后將該文件加載到DistributeCache中。
         接下來是Task B,該任務(wù)是一個(gè)沒有Reduce的MR,啟動(dòng)MapTasks掃描大表a,在Map階段,根據(jù)a的每一條記錄去和DistributeCache中b表對應(yīng)的HashTable關(guān)聯(lián),并直接輸出結(jié)果。
         由于MapJoin沒有Reduce,所以由Map直接輸出結(jié)果文件,有多少個(gè)Map Task,就有多少個(gè)結(jié)果文件。
案例實(shí)操:

  1. 開啟Mapjoin功能

set hive.auto.convert.join = true; -- 默認(rèn)為true
  1. 執(zhí)行小表JOIN大表語句

INSERT OVERWRITE TABLE jointable2SELECT b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_urlFROM smalltable sJOIN bigtable  bON s.id = b.id;OK
b.id    b.time  b.uid   b.keyword       b.url_rank      b.click_num     b.click_urlTime taken: 18.057 seconds

3.執(zhí)行大表JOIN小表語句

INSERT OVERWRITE TABLE jointable2SELECT b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_urlFROM smalltable sJOIN bigtable  bON s.id = b.id;OK
b.id    b.time  b.uid   b.keyword       b.url_rank      b.click_num     b.click_urlTime taken: 12.822 seconds

以上是“Hive的調(diào)優(yōu)有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!


當(dāng)前文章:Hive的調(diào)優(yōu)有哪些
文章路徑:http://weahome.cn/article/gdsocj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部