溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Hive性能調(diào)優(yōu)中Fetch抓取的示例分析

發(fā)布時間:2021-12-10 10:58:37 來源:億速云 閱讀:125 作者:小新 欄目:大數(shù)據(jù)

這篇文章主要為大家展示了“Hive性能調(diào)優(yōu)中Fetch抓取的示例分析”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Hive性能調(diào)優(yōu)中Fetch抓取的示例分析”這篇文章吧。

我們在剛開始學(xué)習(xí)hive的時候,都知道hive可以降低程序員的學(xué)習(xí)成本和開發(fā)成本,具體表現(xiàn)就在于可以將SQL語句轉(zhuǎn)換成MapReduce程序運(yùn)行。

但是Hive中對某些情況的查詢可以不必使用MapReduce計(jì)算。例如:SELECT * FROM employees;在這種情況下,Hive可以簡單地讀取employee對應(yīng)的存儲目錄下的文件,然后輸出查詢結(jié)果到控制臺。

在hive-default.xml.template文件中hive.fetch.task.conversion默認(rèn)是more,老版本hive默認(rèn)是minimal,該屬性修改為more以后,在全局查找、字段查找、limit查找等都不走mapreduce。

<property>
   <name>hive.fetch.task.conversion</name>
   <value>more</value>
   <description>
     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
   </description>
 </property>
 

接下來讓我們通過一些實(shí)操,來查看一下效果!

 
案例實(shí)操

把hive.fetch.task.conversion設(shè)置成none,然后執(zhí)行查詢語句,都會執(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;
 

Hive性能調(diào)優(yōu)中Fetch抓取的示例分析

把hive.fetch.task.conversion設(shè)置成more,然后執(zhí)行查詢語句,如下查詢方式都不會執(zhí)行mapreduce程序。

hive (default)> set hive.fetch.task.conversion=more;
hive (default)> select * from score;
hive (default)> select s_score from score;
hive (default)> select s_score from score limit 3;
 

Hive性能調(diào)優(yōu)中Fetch抓取的示例分析

們可以明顯發(fā)現(xiàn)當(dāng)把hive.fetch.task.conversion設(shè)置成none,所有的程序都走mapreduce程序會耗費(fèi)一定的時間。但就算設(shè)置成none,也只有部分sql語句會不走mapreduce程序,那有沒有什么辦法可以優(yōu)化這個問題呢?

 

本地模式

大多數(shù)的Hadoop Job是需要Hadoop提供的完整的可擴(kuò)展性來處理大數(shù)據(jù)集的。不過,有時Hive的輸入數(shù)據(jù)量是非常小的。在這種情況下,為查詢觸發(fā)執(zhí)行任務(wù)時消耗可能會比實(shí)際job的執(zhí)行時間要多的多。對于大多數(shù)這種情況,Hive可以通過本地模式在單臺機(jī)器上處理所有的任務(wù)。對于小數(shù)據(jù)集,使用本地模式執(zhí)行時間可以明顯被縮短。

用戶可以通過設(shè)置hive.exec.mode.local.auto的值為true,來讓Hive在適當(dāng)?shù)臅r候自動啟動這個優(yōu)化。

set hive.exec.mode.local.auto=true; //開啟本地mr

設(shè)置local mr的最大輸入數(shù)據(jù)量,當(dāng)輸入數(shù)據(jù)量小于這個值時采用local mr的方式,默認(rèn)為134217728,即128M

set hive.exec.mode.local.auto.inputbytes.max=51234560;

設(shè)置local mr的最大輸入文件個數(shù),當(dāng)輸入文件個數(shù)小于這個值時采用local mr的方式,默認(rèn)為4

set 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;
 

18 rows selected (1.568 seconds)

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

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

18 rows selected (11.865 seconds)

 
Group By

默認(rèn)情況下,Map階段同一Key數(shù)據(jù)分發(fā)給一個reduce,當(dāng)一個key數(shù)據(jù)過大時就傾斜了。

并不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端進(jìn)行部分聚合,最后在Reduce端得出最終結(jié)果。

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

set hive.map.aggr = true;

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

set hive.groupby.mapaggr.checkinterval = 100000;

有數(shù)據(jù)傾斜的時候進(jìn)行負(fù)載均衡(默認(rèn)是false)

set hive.groupby.skewindata = true;

當(dāng)選項(xiàng)設(shè)定為 true,生成的查詢計(jì)劃會有兩個MR Job。第一個MR Job中,Map的輸出結(jié)果會隨機(jī)分布到Reduce中,每個Reduce做部分聚合操作,并輸出結(jié)果,這樣處理的結(jié)果是相同的Group By Key有可能被分發(fā)到不同的Reduce中,從而達(dá)到負(fù)載均衡的目的;第二個MR Job再根據(jù)預(yù)處理的數(shù)據(jù)結(jié)果按照Group By Key分布到Reduce中(這個過程可以保證相同的Group By Key被分布到同一個Reduce中),最后完成最終的聚合操作。

 
Count(distinct)

數(shù)據(jù)量小的時候無所謂,數(shù)據(jù)量大的情況下,由于COUNT DISTINCT操作需要用一個Reduce Task來完成,這一個Reduce需要處理的數(shù)據(jù)量太大,就會導(dǎo)致整個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/admin/softwares/data/100萬條大表數(shù)據(jù)(id除以10取整)/bigtable' into table bigtable;
set hive.exec.reducers.bytes.per.reducer=32123456;
 

測試: SELECT count(DISTINCT id) FROM bigtable;

結(jié)果: c0 10000 Time 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 _c0 10000 Time taken: 51.202 seconds, Fetched: 1 row(s)

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

 
笛卡爾積

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

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

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

環(huán)境準(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/admin/softwares/data/加遞增id的原始數(shù)據(jù)/ori' into table ori;
load data local inpath '/home/admin/softwares/data/100萬條大表數(shù)據(jù)(id除以10取整)/bigtable' into table bigtable;
 

先關(guān)聯(lián)再Where:

SELECT a.id
FROM bigtable a
LEFT JOIN ori b ON a.id = b.id
WHERE b.id <= 10;
 

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

SELECT a.id
FROM ori a
LEFT JOIN bigtable b ON (b.id <= 10 AND a.id = b.id);
 

或者直接寫成子查詢:

SELECT a.id
FROM bigtable a
RIGHT JOIN (SELECT id
FROM ori
WHERE id <= 10
) b ON a.id = b.id;
   

動態(tài)分區(qū)調(diào)整

關(guān)系型數(shù)據(jù)庫中,對分區(qū)表Insert數(shù)據(jù)時候,數(shù)據(jù)庫自動會根據(jù)分區(qū)字段的值,將數(shù)據(jù)插入到相應(yīng)的分區(qū)中,Hive中也提供了類似的機(jī)制,即動態(tài)分區(qū)(Dynamic Partition),只不過,使用Hive的動態(tài)分區(qū),需要進(jìn)行相應(yīng)的配置。以第一個表的分區(qū)規(guī)則,來對應(yīng)第二個表的分區(qū)規(guī)則,將第一個表的所有分區(qū),全部拷貝到第二個表中來,第二個表在加載數(shù)據(jù)的時候,不需要指定分區(qū)了,直接用第一個表的分區(qū)即可

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

①set hive.exec.dynamic.partition=true;

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

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

④在每個執(zhí)行MR的節(jié)點(diǎn)上,最大可以創(chuàng)建多少個動態(tài)分區(qū)。該參數(shù)需要根據(jù)實(shí)際的數(shù)據(jù)來設(shè)定。比如:源數(shù)據(jù)中包含了一年的數(shù)據(jù),即day字段有365個值,那么該參數(shù)就需要設(shè)置成大于365,如果使用默認(rèn)值100,則會報(bào)錯。set hive.exec.max.dynamic.partitions.pernode=100

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

⑥當(dāng)有空分區(qū)生成時,是否拋出異常。一般不需要設(shè)置。set hive.error.on.empty.partition=false;

 
案例實(shí)操

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

①準(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 '/export/servers/hivedatas/small_data' into  table ori_partitioned partition (p_time='20111230000010');
load data local inpath '/export/servers/hivedatas/small_data' into  table ori_partitioned partition (p_time='20111230000011');
 

②創(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';
 

③分析 如果按照之前介紹的往指定一個分區(qū)中Insert數(shù)據(jù),那么這個需求很不容易實(shí)現(xiàn)。這時候就需要使用動態(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 (month,day)中指定分區(qū)字段名即可;在SELECT子句的最后幾個字段,必須對應(yīng)前面PARTITION (month,day)中指定的分區(qū)字段,包括順序。查看分區(qū):

hive> show partitions ori_partitioned_target; 
OK
p_time=20111230000010
p_time=20111230000011

以上是“Hive性能調(diào)優(yōu)中Fetch抓取的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI