Fetch 抓取
Fetch抓取是指初家,Hive中對某些情況的查詢可以不必使用MapReduce計算。例如:SELECT * FROM employees;在這種情況下乌助,Hive可以簡單地讀取employee對應(yīng)的存儲目錄下的文件溜在,然后輸出查詢結(jié)果到控制臺。
在hive-default.xml.template文件中hive.fetch.task.conversion默認是more他托,老版本hive默認是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 laten
cy.
Currently the query should be single sourced not having any subquery and s
hould not have
any aggregations or distincts (which incurs RS), lateral views and joins.
0. none : disable hive.fetch.task.conversion
1. minimal : SELECT STAR, FILTER on partition columns, LIMIT only
2. more : SELECT, FILTER, LIMIT only (support TABLESAMPLE and virtual c
olumns)
</description>
</property>
進行如下實驗
- 把hive.fetch.task.conversion設(shè)置成none
執(zhí)行查詢語句沿盅,都會執(zhí)行mapreduce程序
set hive.fetch.task.conversion=none;
select * from emp;
select ename from emp;
select ename from emp limit 3;
- 把hive.fetch.task.conversion設(shè)置成more
執(zhí)行查詢語句,如下查詢方式都不會執(zhí)行mapreduce程序
set hive.fetch.task.conversion=more;
select * from emp;
select ename from emp;
select ename from emp limit 3;
本地模式
大多數(shù)的Hadoop Job是需要Hadoop提供的完整的可擴展性來處理大數(shù)據(jù)集的籽腕。不過嗡呼,有時Hive的輸入數(shù)據(jù)量是非常小的。在這種情況下皇耗,為查詢觸發(fā)執(zhí)行任務(wù)消耗的時間可能會比實際job的執(zhí)行時間要多的多南窗。對于大多數(shù)這種情況,Hive可以通過本地模式在單臺機器上處理所有的任務(wù)郎楼。對于小數(shù)據(jù)集万伤,執(zhí)行時間可以明顯被縮短。
相關(guān)的參數(shù)默認值如下
<property>
<name>hive.exec.mode.local.auto</name>
<value>false</value>
<description>Let Hive determine whether to run in local mode automatically</description>
</property>
<property>
<name>hive.exec.mode.local.auto.inputbytes.max</name>
<value>134217728</value>
<description>When hive.exec.mode.local.auto is true, input bytes should less than this for local mode.</d
escription>
</property>
<property>
<name>hive.exec.mode.local.auto.input.files.max</name>
<value>4</value>
<description>When hive.exec.mode.local.auto is true, the number of tasks should less than this for local
mode.</description>
</property>
進行如下實驗呜袁,運行select * from emp cluster by deptno;
默認的模式下運行敌买,結(jié)果如下
開啟本地模式運行,結(jié)果如下
set hive.exec.mode.local.auto=true;
表的優(yōu)化
小表阶界、大表Join
將key相對分散虹钮,并且數(shù)據(jù)量小的表放在join的左邊,這樣可以有效減少內(nèi)存溢出錯誤發(fā)生的幾率膘融;再進一步芙粱,可以使用map join讓小的維度表(1000條以下的記錄條數(shù))先進內(nèi)存。在map端完成reduce氧映。
新版的hive已經(jīng)對小表JOIN大表和大表JOIN小表進行了優(yōu)化春畔。小表放在左邊和右邊已經(jīng)沒有明顯區(qū)別
案例
-
數(shù)據(jù)準備
小表和大表.png - 創(chuàng)建大表、小表和join后表語句
-- 創(chuàng)建大表
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';
-- 創(chuàng)建小表
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';
-- 創(chuàng)建join后表的語句
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';
- 導入數(shù)據(jù)
load data local inpath '/opt/module/datas/bigtable' into table bigtable;
load data local inpath '/opt/module/datas/smalltable' into table smalltable;
- 關(guān)閉mapjoin功能(默認是打開的)
set hive.auto.convert.join = false;
<property>
<name>hive.auto.convert.join</name>
<value>true</value>
<description>Whether Hive enables the optimization about converting common join into mapjoin based on the
input file size</description>
</property>
- 執(zhí)行小表join大表
insert overwrite table jointable
select b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from smalltable s
left join bigtable b
on b.id = s.id;
- 執(zhí)行大表join小表
insert overwrite table jointable
select b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from bigtable b
left join smalltable s
on s.id = b.id;
大表Join大表
空key過濾
有時join超時是因為某些key對應(yīng)的數(shù)據(jù)太多岛都,而相同key對應(yīng)的數(shù)據(jù)都會發(fā)送到相同的reducer上律姨,從而導致內(nèi)存不夠。此時我們應(yīng)該仔細分析這些異常的key臼疫,很多情況下择份,這些key對應(yīng)的數(shù)據(jù)是異常數(shù)據(jù),我們需要在SQL語句中進行過濾烫堤。例如key對應(yīng)的字段為空
案例
-
數(shù)據(jù)準備
數(shù)據(jù)準備.png - 配置歷史服務(wù)器
在運行ResourceManager服務(wù)的服務(wù)器下進行如下配置荣赶,修改mapred-site.xml文件,添加如下內(nèi)容
<property>
<name>mapreduce.jobhistory.address</name>
<value>hadoop-101:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>hadoop-101:19888</value>
</property>
- 啟用日志聚集功能
在hadoop的每臺服務(wù)器上塔逃,做如下配置讯壶,修改yarn-site.xml
<!-- 日志聚集功能使能 -->
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<!-- 日志保留時間設(shè)置7天 -->
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>604800</value>
</property>
- 重啟hdfs、yarn湾盗,啟動歷史服務(wù)器功能
stop-yarn.sh
stop-dfs.sh
start-yarn.sh
start-dfs.sh
mr-jobhistory-daemon.sh start historyserver - 創(chuàng)建相關(guān)表
-- 創(chuà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';
-- 創(chuàng)建空id表
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';
-- 創(chuàng)建join后表的語句
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';
- 導入數(shù)據(jù)
load data local inpath '/opt/module/datas/ori' into table ori;
load data local inpath '/opt/module/datas/nullid' into table nullidtable;
-
測試不過濾空id
insert overwrite table jointable select n.* from nullidtable n left join ori o on n.id = o.id;
不過濾空值.png -
測試過濾空id
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;
過濾空值.png
空key轉(zhuǎn)換
有時雖然某個key為空對應(yīng)的數(shù)據(jù)很多伏蚊,但是相應(yīng)的數(shù)據(jù)不是異常數(shù)據(jù),必須要包含在join的結(jié)果中格粪,此時我們可以表a中key為空的字段賦一個隨機的值躏吊,使得數(shù)據(jù)隨機均勻地分不到不同的reducer上
案例
- 不隨機分布空null值
1). 設(shè)置5個reduce個數(shù)
set mapreduce.job.reduces = 5;
2). JOIN兩張表
insert overwrite table jointable select n.* from nullidtable n left join ori b on n.id = b.id;
可以看出來氛改,出現(xiàn)了數(shù)據(jù)傾斜,某些reducer的資源消耗遠大于其他reducer
- 隨機分布空null值
1) . 設(shè)置5個reduce個數(shù)
set mapreduce.job.reduces = 5;
2). JOIN兩張表
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;
可以看出來比伏,消除了數(shù)據(jù)傾斜胜卤,負載均衡reducer的資源消耗
MapJoin
如果不指定MapJoin或者不符合MapJoin的條件,那么Hive解析器會將Join操作轉(zhuǎn)換成Common Join赁项,即在Reduce階段完成join葛躏。容易發(fā)生數(shù)據(jù)傾斜∮撇耍可以用MapJoin把小表全部加載到內(nèi)存在map端進行join舰攒,避免reducer處理
相關(guān)參數(shù)設(shè)置
- 設(shè)置自動選擇Mapjoin
set hive.auto.convert.join = true; 默認為true - 大表小表的閾值設(shè)置
set hive.mapjoin.smalltable.filesize=25000000;
默認配置在配置文件中如下
<property>
<name>hive.auto.convert.join</name>
<value>true</value>
<description>Whether Hive enables the optimization about converting common join into mapjoin based on the
input file size</description>
</property>
<property>
<name>hive.mapjoin.smalltable.filesize</name>
<value>25000000</value>
<description>
The threshold for the input file size of the small tables; if the file size is smaller
than this threshold, it will try to convert the common join into map join
</description>
</property>
MapJoin原理如下
MapJoin相關(guān)案例實操在大表join小表和小表join大小已經(jīng)做過了,這里就不再重復(fù)了
Group By
默認情況下悔醋,Map階段同一Key數(shù)據(jù)分發(fā)給一個reduce摩窃,當一個key數(shù)據(jù)過大時就傾斜了。
并不是所有的聚合操作都需要在Reduce端完成芬骄,很多聚合操作都可以先在Map端進行部分聚合猾愿,最后在Reduce端得出最終結(jié)果。
相關(guān)參數(shù)設(shè)置
- 是否在Map端進行聚合账阻,默認為True
hive.map.aggr = true - 在Map端進行聚合操作的條目數(shù)目
hive.groupby.mapaggr.checkinterval = 100000 - 有數(shù)據(jù)傾斜的時候進行負載均衡(默認是false)
hive.groupby.skewindata = true
默認配置在配置文件中如下
<property>
<name>hive.map.aggr</name>
<value>true</value>
<description>Whether to use map-side aggregation in Hive Group By queries</description>
</property>
<property>
<name>hive.groupby.mapaggr.checkinterval</name>
<value>100000</value>
<description>Number of rows after which size of the grouping keys/aggregation classes is performed</descr
iption>
</property>
<property>
<name>hive.groupby.skewindata</name>
<value>false</value>
<description>Whether there is skew in data to optimize group by queries</description>
</property>
當選項設(shè)定為 true蒂秘,生成的查詢計劃會有兩個MR Job。第一個MR Job中宰僧,Map的輸出結(jié)果會隨機分布到Reduce中材彪,每個Reduce做部分聚合操作观挎,并輸出結(jié)果琴儿,這樣處理的結(jié)果是相同的Group By Key有可能被分發(fā)到不同的Reduce中,從而達到負載均衡的目的嘁捷;第二個MR Job再根據(jù)預(yù)處理的數(shù)據(jù)結(jié)果按照Group By Key分布到Reduce中(這個過程可以保證相同的Group By Key被分布到同一個Reduce中)造成,最后完成最終的聚合操作。
Count(Distinct) 去重統(tǒng)計
數(shù)據(jù)量小的時候無所謂雄嚣,數(shù)據(jù)量大的情況下晒屎,由于COUNT DISTINCT操作需要用一個Reduce Task來完成,這一個Reduce需要處理的數(shù)據(jù)量太大缓升,就會導致整個Job很難完成鼓鲁,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替換
案例
- 設(shè)置5個reduce個數(shù)
set mapreduce.job.reduces = 5; - 執(zhí)行去重id查詢
select count(distinct id) from bigtable;
結(jié)果如下
- 采用GROUP by去重id
select count(id) from (select id from bigtable group by id) a;
結(jié)果如下
雖然會多用一個Job來完成,但在數(shù)據(jù)量大的情況下港谊,這個絕對是值得的
笛卡爾積
盡量避免笛卡爾積骇吭,join的時候不加on條件,或者無效的on條件歧寺,Hive只能使用1個reducer來完成笛卡爾積
行列過濾
列處理:在SELECT中燥狰,只拿需要的列棘脐,如果有,盡量使用分區(qū)過濾龙致,少用SELECT *蛀缝。
行處理:在分區(qū)剪裁中,當使用外關(guān)聯(lián)時目代,如果將副表的過濾條件寫在Where后面屈梁,那么就會先全表關(guān)聯(lián),之后再過濾
案例
- 先關(guān)聯(lián)兩張表榛了,再用where條件過濾
select o.id from bigtable b join ori o on o.id = b.id where o.id <= 10;
- 通過子查詢俘闯,再關(guān)聯(lián)表
select b.id from bigtable b join (select * from ori where id < 10) o on b.id = o.id;
動態(tài)分區(qū)調(diào)整
關(guān)系型數(shù)據(jù)庫中,對分區(qū)表Insert數(shù)據(jù)時候忽冻,數(shù)據(jù)庫自動會根據(jù)分區(qū)字段的值真朗,將數(shù)據(jù)插入到相應(yīng)的分區(qū)中,Hive中也提供了類似的機制僧诚,即動態(tài)分區(qū)(Dynamic Partition)遮婶,只不過,使用Hive的動態(tài)分區(qū)湖笨,需要進行相應(yīng)的配置
- 開啟動態(tài)分區(qū)功能(默認true旗扑,開啟)
hive.exec.dynamic.partition=true - 設(shè)置為非嚴格模式(動態(tài)分區(qū)的模式,默認strict慈省,表示必須指定至少一個分區(qū)為靜態(tài)分區(qū)臀防,nonstrict模式表示允許所有的分區(qū)字段都可以使用動態(tài)分區(qū)。)
hive.exec.dynamic.partition.mode=nonstrict - 在所有執(zhí)行MR的節(jié)點上边败,最大一共可以創(chuàng)建多少個動態(tài)分區(qū)袱衷。
hive.exec.max.dynamic.partitions=1000 - 在每個執(zhí)行MR的節(jié)點上,最大可以創(chuàng)建多少個動態(tài)分區(qū)笑窜。該參數(shù)需要根據(jù)實際的數(shù)據(jù)來設(shè)定致燥。比如:源數(shù)據(jù)中包含了一年的數(shù)據(jù),即day字段有365個值排截,那么該參數(shù)就需要設(shè)置成大于365嫌蚤,如果使用默認值100,則會報錯断傲。
hive.exec.max.dynamic.partitions.pernode=100 - 整個MR Job中脱吱,最大可以創(chuàng)建多少個HDFS文件。
hive.exec.max.created.files=100000 - 當有空分區(qū)生成時认罩,是否拋出異常箱蝠。一般不需要設(shè)置。
hive.error.on.empty.partition=false
上述信息在默認文件的配置如下
<property>
<name>hive.mapred.reduce.tasks.speculative.execution</name>
<value>true</value>
<description>Whether speculative execution for reducers should be turned on. </description>
</property>
<property>
<name>hive.exec.counters.pull.interval</name>
<value>1000</value>
<description>
The interval with which to poll the JobTracker for the counters the running job.
The smaller it is the more load there will be on the jobtracker, the higher it is the less granular the
caught will be.
</description>
</property>
<property>
<name>hive.exec.dynamic.partition</name>
<value>true</value>
<description>Whether or not to allow dynamic partitions in DML/DDL.</description>
</property>
<property>
<name>hive.exec.dynamic.partition.mode</name>
<value>strict</value>
<description>
In strict mode, the user must specify at least one static partition
in case the user accidentally overwrites all partitions.
In nonstrict mode all partitions are allowed to be dynamic.
</description>
</property>
<property>
<name>hive.exec.max.dynamic.partitions</name>
<value>1000</value>
<description>Maximum number of dynamic partitions allowed to be created in total.</description>
</property>
<property>
<name>hive.exec.max.dynamic.partitions.pernode</name>
<value>100</value>
<description>Maximum number of dynamic partitions allowed to be created in each mapper/reducer node.</des
cription>
</property>
<property>
<name>hive.exec.max.created.files</name>
<value>100000</value>
<description>Maximum number of HDFS files created by all mappers/reducers in a MapReduce job.</descriptio
n>
</property>
<property>
<name>hive.error.on.empty.partition</name>
<value>false</value>
<description>Whether to throw an exception if dynamic partition insert generates empty results.</descript
ion>
</property>
案例實操
需求:將ori中的數(shù)據(jù)按照時間(如:20111230000008),插入到目標表ori_partitioned_target的相應(yīng)分區(qū)中
-- 創(chuàng)建分區(qū)表
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';
-- 加載數(shù)據(jù)到分區(qū)表中
load data local inpath '/opt/module/datas/ds1' into table ori_partitioned partition(p_time='20111230000010') ;
load data local inpath '/opt/module/datas/ds2' 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';
-- 設(shè)置動態(tài)分區(qū)
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;
-- 上傳數(shù)據(jù)
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;
-- 查看目標分區(qū)表的分區(qū)情況
show partitions ori_partitioned_target;
分桶
見之前文章抡锈,http://www.reibang.com/p/406c2f15dc0b
分區(qū)
見之前文章疾忍,http://www.reibang.com/p/0e7efeace775
數(shù)據(jù)傾斜
合理設(shè)置Map數(shù)
- 通常情況下,作業(yè)會通過input的目錄產(chǎn)生一個或者多個map任務(wù)
主要的決定因素有:input的文件總個數(shù)床三,input的文件大小一罩,集群設(shè)置的文件塊大小 - 是不是map數(shù)越多越好?
答案是否定的撇簿。如果一個任務(wù)有很多小文件(遠遠小于塊大小128m)聂渊,則每個小文件也會被當做一個塊,用一個map任務(wù)來完成四瘫,而一個map任務(wù)啟動和初始化的時間遠遠大于邏輯處理的時間汉嗽,就會造成很大的資源浪費。而且找蜜,同時可執(zhí)行的map數(shù)是受限的 - 是不是保證每個map處理接近128m的文件塊饼暑,就高枕無憂了?
答案也是不一定洗做。比如有一個127m的文件弓叛,正常會用一個map去完成,但這個文件只有一個或者兩個小字段诚纸,卻有幾千萬的記錄撰筷,如果map處理的邏輯比較復(fù)雜,用一個map任務(wù)去做畦徘,肯定也比較耗時毕籽。
針對上面的問題2和3,我們需要采取兩種方式來解決:即減少map數(shù)和增加map數(shù)
小文件進行合并
在map執(zhí)行前合并小文件井辆,減少map數(shù):CombineHiveInputFormat具有對小文件進行合并的功能(系統(tǒng)默認的格式)关筒。HiveInputFormat沒有對小文件合并功能
<property>
<name>hive.input.format</name>
<value>org.apache.hadoop.hive.ql.io.CombineHiveInputFormat</value>
<description>The default input format. Set this to HiveInputFormat if you encounter problems with Combine
HiveInputFormat.</description>
</property>
復(fù)雜文件增加map數(shù)
當input的文件都很大,任務(wù)邏輯復(fù)雜掘剪,map執(zhí)行非常慢的時候平委,可以考慮增加Map數(shù)奈虾,來使得每個map處理的數(shù)據(jù)量減少夺谁,從而提高任務(wù)的執(zhí)行效率。
增加map的方法為,根據(jù)computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M公式肉微,調(diào)整maxSize最大值匾鸥。讓maxSize最大值低于blocksize就可以增加map的個數(shù)
案例
- 執(zhí)行查詢
select count(*) from emp;
- 設(shè)置最大切片值為50個字節(jié)
set mapreduce.input.fileinputformat.split.maxsize=50;
select count(*) from emp;
合理設(shè)置Reduce數(shù)
調(diào)整reduce個數(shù)方法一
- Reduce處理的數(shù)據(jù)量默認是256MB
hive.exec.reducers.bytes.per.reducer=256000000 - 每個任務(wù)最大的reduce數(shù),默認為1009
hive.exec.reducers.max=1009 - 計算reducer數(shù)的公式
N=min(參數(shù)2碉纳,總輸入數(shù)據(jù)量/參數(shù)1)
上面兩個參數(shù)的默認配置如下
<property>
<name>hive.exec.reducers.bytes.per.reducer</name>
<value>256000000</value>
<description>size per reducer.The default is 256Mb, i.e if the input size is 1G, it will use 4 reducers.<
/description>
</property>
<property>
<name>hive.exec.reducers.max</name>
<value>1009</value>
<description>
max number of reducers will be used. If the one specified in the configuration parameter mapred.reduce.
tasks is
negative, Hive will use this one as the max number of reducers when automatically determine number of r
educers.
</description>
</property>
調(diào)整reduce個數(shù)方法二
在hadoop的mapred-default.xml文件中修改勿负,設(shè)置設(shè)置每個job的Reduce個數(shù)
set mapreduce.job.reduces = 15;
reduce個數(shù)并不是越多越好
- 過多的啟動和初始化reduce也會消耗時間和資源;
- 另外,有多少個reduce奴愉,就會有多少個輸出文件琅摩,如果生成了很多個小文件,那么如果這些小文件作為下一個任務(wù)的輸入锭硼,則也會出現(xiàn)小文件過多的問題房资;
在設(shè)置reduce個數(shù)的時候也需要考慮這兩個原則,處理大數(shù)據(jù)量利用合適的reduce數(shù)檀头,使單個reduce任務(wù)處理數(shù)據(jù)量大小要合適轰异;
并行執(zhí)行
Hive會將一個查詢轉(zhuǎn)化成一個或者多個階段。這樣的階段可以是MapReduce階段暑始、抽樣階段搭独、合并階段、limit階段廊镜⊙栏危或者Hive執(zhí)行過程中可能需要的其他階段。默認情況下嗤朴,Hive一次只會執(zhí)行一個階段惊奇。不過,某個特定的job可能包含眾多的階段播赁,而這些階段可能并非完全互相依賴的颂郎,也就是說有些階段是可以并行執(zhí)行的,這樣可能使得整個job的執(zhí)行時間縮短容为。不過乓序,如果有更多的階段可以并行執(zhí)行,那么job可能就越快完成
通過設(shè)置參數(shù)hive.exec.parallel值為true坎背,就可以開啟并發(fā)執(zhí)行替劈。不過,在共享集群中得滤,需要注意下陨献,如果job中并行階段增多,那么集群利用率就會增加
當然懂更,得是在系統(tǒng)資源比較空閑的時候才有優(yōu)勢眨业,否則,沒資源沮协,并行也起不來
set hive.exec.parallel=true; //打開任務(wù)并行執(zhí)行
set hive.exec.parallel.thread.number=16; //同一個sql允許最大并行度龄捡,默認為8。
<property>
<name>hive.exec.parallel</name>
<value>false</value>
<description>Whether to execute jobs in parallel</description>
</property>
<property>
<name>hive.exec.parallel.thread.number</name>
<value>8</value>
<description>How many jobs at most can be executed in parallel</description>
</property>
嚴格模式
Hive提供了一個嚴格模式慷暂,可以防止用戶執(zhí)行那些可能意向不到的不好的影響的查詢聘殖。
通過設(shè)置屬性hive.mapred.mode值為默認是非嚴格模式nonstrict 。開啟嚴格模式需要修改hive.mapred.mode值為strict,開啟嚴格模式可以禁止3種類型的查詢
- 對于分區(qū)表奸腺,除非where語句中含有分區(qū)字段過濾條件來限制范圍餐禁,否則不允許執(zhí)行。換句話說突照,就是用戶不允許掃描所有分區(qū)坠宴。進行這個限制的原因是,通常分區(qū)表都擁有非常大的數(shù)據(jù)集绷旗,而且數(shù)據(jù)增加迅速喜鼓。沒有進行分區(qū)限制的查詢可能會消耗令人不可接受的巨大資源來處理這個表。
- 對于使用了order by語句的查詢衔肢,要求必須使用limit語句庄岖。因為order by為了執(zhí)行排序過程會將所有的結(jié)果數(shù)據(jù)分發(fā)到同一個Reducer中進行處理,強制要求用戶增加這個LIMIT語句可以防止Reducer額外執(zhí)行很長一段時間角骤。
- 限制笛卡爾積的查詢隅忿。對關(guān)系型數(shù)據(jù)庫非常了解的用戶可能期望在執(zhí)行JOIN查詢的時候不使用ON語句而是使用where語句,這樣關(guān)系數(shù)據(jù)庫的執(zhí)行優(yōu)化器就可以高效地將WHERE語句轉(zhuǎn)化成那個ON語句邦尊。不幸的是背桐,Hive并不會執(zhí)行這種優(yōu)化,因此蝉揍,如果表足夠大链峭,那么這個查詢就會出現(xiàn)不可控的情況。
<property>
<name>hive.mapred.mode</name>
<value>nonstrict</value>
<description>
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.
</description>
</property>
JVM重用
JVM重用是Hadoop調(diào)優(yōu)參數(shù)的內(nèi)容又沾,其對Hive的性能具有非常大的影響弊仪,特別是對于很難避免小文件的場景或task特別多的場景,這類場景大多數(shù)執(zhí)行時間都很短杖刷。
Hadoop的默認配置通常是使用派生JVM來執(zhí)行map和Reduce任務(wù)的励饵。這時JVM的啟動過程可能會造成相當大的開銷,尤其是執(zhí)行的job包含有成百上千task任務(wù)的情況滑燃。JVM重用可以使得JVM實例在同一個job中重新使用N次役听。N的值可以在Hadoop的mapred-site.xml文件中進行配置。通常在10-20之間表窘,具體多少需要根據(jù)具體業(yè)務(wù)場景測試得出
這個功能的缺點是典予,開啟JVM重用將一直占用使用到的task插槽,以便進行重用蚊丐,直到任務(wù)完成后才能釋放熙参。如果某個“不平衡的”job中有某幾個reduce task執(zhí)行的時間要比其他Reduce task消耗的時間多的多的話,那么保留的插槽就會一直空閑著卻無法被其他的job使用麦备,直到所有的task都結(jié)束了才會釋放
<property>
<name>mapreduce.job.jvm.numtasks</name>
<value>10</value>
<description>How many tasks to run per jvm. If set to -1, there is
no limit.
</description>
</property>
推測執(zhí)行
在分布式集群環(huán)境下,因為程序Bug(包括Hadoop本身的bug),負載不均衡或者資源分布不均等原因凛篙,會造成同一個作業(yè)的多個任務(wù)之間運行速度不一致黍匾,有些任務(wù)的運行速度可能明顯慢于其他任務(wù)(比如一個作業(yè)的某個任務(wù)進度只有50%,而其他所有任務(wù)已經(jīng)運行完畢)呛梆,則這些任務(wù)會拖慢作業(yè)的整體執(zhí)行進度锐涯。為了避免這種情況發(fā)生,Hadoop采用了推測執(zhí)行(Speculative Execution)機制填物,它根據(jù)一定的法則推測出“拖后腿”的任務(wù)纹腌,并為這樣的任務(wù)啟動一個備份任務(wù),讓該任務(wù)與原始任務(wù)同時處理同一份數(shù)據(jù)滞磺,并最終選用最先成功運行完成任務(wù)的計算結(jié)果作為最終結(jié)果升薯。
設(shè)置開啟推測執(zhí)行參數(shù):Hadoop的mapred-site.xml文件中進行配置
<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>
不過hive本身也提供了配置項來控制reduce-side的推測執(zhí)行
<property>
<name>hive.mapred.reduce.tasks.speculative.execution</name>
<value>true</value>
<description>Whether speculative execution for reducers should be turned on. </description>
</property>
關(guān)于調(diào)優(yōu)這些推測執(zhí)行變量,還很難給一個具體的建議击困。如果用戶對于運行時的偏差非常敏感的話涎劈,那么可以將這些功能關(guān)閉掉。如果用戶因為輸入數(shù)據(jù)量很大而需要執(zhí)行長時間的map或者Reduce task的話阅茶,那么啟動推測執(zhí)行造成的浪費是非常巨大大
壓縮
參考之前的文章蛛枚,http://www.reibang.com/p/0a83ea228c77
執(zhí)行計劃(Explain)
- 基本語法
EXPLAIN [EXTENDED | DEPENDENCY | AUTHORIZATION] query - 案例實操
(1). 查看下面這條語句的執(zhí)行計劃
explain select * from emp;
explain select deptno, avg(sal) avg_sal from emp group by deptno;
(2). 查看詳細執(zhí)行計劃
explain extended select * from emp;
explain extended select deptno, avg(sal) avg_sal from emp group by deptno;