Hive作為大資料領域常用的資料倉庫組件,在設計和開發階段需要注意效率,影響Hive效率的不僅僅是資料量過大;資料傾斜、資料冗余、job或I/O過多、MapReduce分配不合理等因素都對Hive的效率有影響,對Hive的調優既包含對HiveQL陳述句本身的優化,也包含Hive配置項和MR方面的調
整,
從以下三個方面展開:
架構優化
引數優化
SQL優化
1.架構方面
執行引擎方面針對公司內平臺的資源,選擇更合適的更快的引擎,比如MR、TEZ、Spark等,
如果選擇是TEZ引擎,可以在優化器時候開啟向量化的優化器,另外可以選擇成本優化器CBO,配置分別如下:
set hive.vectorized.execution.enabled = true; -
- 默認 false
set hive.vectorized.execution.reduce.enabled = true; -
- 默認 false
SET hive.cbo.enable=true; --從 v0.14.0默認
true
SET hive.compute.query.using.stats=true; -- 默認false
SET hive.stats.fetch.column.stats=true; -- 默認false
SET hive.stats.fetch.partition.stats=true; -- 默認true
在表的設計上優化,比如選擇磁區表,分桶表,以及表的存盤格式,為了減少資料傳輸,可以使用壓縮的方式,下面給幾個引數(更多引數可以查看官網)
-- 中間結果壓縮
SET
hive.intermediate.compression.codec=org.apache.hadoop.io.compress.SnappyCodec ;
-- 輸出結果壓縮
SET hive.exec.compress.output=true;
SET mapreduce.output.fileoutputformat.compress.codec =org.apache.hadoop.io.compress.SnappyCodc
2.引數優化
第二部分是引數優化,其實上面架構部分,有部分也是通過引數來控制的,這一部分的引數控制主要有下面幾個方面
本地模式、嚴格模式、JVM重用、并行執行、推測執行、合并小檔案、Fetch模式
2.1 本地模式
當資料量較小的時候,啟動分布式處理資料會比較慢,啟動時間較長,不如本地模式快,用下面的引數來調整
SET hive.exec.mode.local.auto=true; -- 默認 false
小
SET hive.exec.mode.local.auto.inputbytes.max=50000000; --輸入檔案的大小小于 hive.exec.mode.local.auto.inputbytes.max 配置的大
SET hive.exec.mode.local.auto.input.files.max=5; -- 默認 4 map任務的數量小于 hive.exec.mode.local.auto.input.files.max 配置的
大小
2.2 嚴格模式
這其實是個開關,滿足下面三個陳述句時候,就會失敗,如果不開啟就正常執行,開啟后就讓這些陳述句自動失敗
hive.mapred.mode=nostrict
-- 查詢磁區表時不限定磁區列的陳述句;
-- 兩表join產生了笛卡爾積的陳述句;
-- 用order by來排序,但沒有指定limit的陳述句
2.3 Jvm重用
在mr里面,是以行程為單位的,一個行程就是一個Jvm,其實像短作業,這些行程能夠重用就會很快,但是它的缺點是會等任務執行完畢后task插槽,這個在資料傾斜時候較為明顯,開啟這個使用下面的引數
SET mapreduce.job.jvm.numtasks=5;
2.4 并行執行
Hive的查詢會轉為stage,這些stage并不是相互依賴的,可以并行執行這些stage,使用下面的引數
SET hive.exec.parallel=true; -- 默認false
SET hive.exec.parallel.thread.number=16; -- 默認8
2.5 推測執行
這個引數的作用是,使用空間資源來換取得到最終結果的時間,比如由于網路,資源不均等原因,某些任務運行特別慢,會啟動備份行程處理同一份資料,并最終選用最先成功的計算結果作為最終結果,
set mapreduce.map.speculative=true
set mapreduce.reduce.speculative=true
set hive.mapred.reduce.tasks.speculative.execution=true
2.6 合并小檔案
在map執行前面,先合并小檔案來減少map數
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
在任務結束后,合并小檔案
# 在 map-only 任務結束時合并小檔案,默認true
SET hive.merge.mapfiles = true;
# 在 map-reduce 任務結束時合并小檔案,默認false
SET hive.merge.mapredfiles = true;
# 合并檔案的大小,默認256M
SET hive.merge.size.per.task = 268435456;
# 當輸出檔案的平均大小小于該值時,啟動一個獨立的map-reduce任務進行檔案merge
SET hive.merge.smallfiles.avgsize = 16777216;
2.7 Fetch模式
最后一種fetch模式,則是在某些情況下盡量不跑mr,比如查詢幾個欄位,全域查找,欄位查,limit查等情況
hive.fetch.task.conversion=more
3.sql優化
這一部分較復雜,可能涉及到資料傾斜問題,至于資料傾斜問題一直是大資料處理的不可比避免的一個問題,處理方式也較多
3.1 sql優化
sql優化是開發人員最容易控制的部分,往往是經驗使之,大約總結一下又下面的方式
列,磁區拆解,sort by 代替 order by, group by 代替count(distinct) ,group by的預聚合(通過引數來控制),傾斜配置項,map join,單獨過濾空值,適當調整map 和 reduces數,這些在作業中幾乎都會碰到,盡可能去優化他們呢是你要做的
3.2 傾斜均衡配置項
這個配置與 group by 的傾斜均衡配置項異曲同工,通過 hive.optimize.skewjoin來配置,默認false,如果開啟了,在join程序中Hive會將計數超過閾值 hive.skewjoin.key (默認100000)的傾斜key對應的行臨時寫進檔案中,然后再啟動另一個job做map join生成結果,通過 hive.skewjoin.mapjoin.map.tasks 引數還可以控制第二個job的mapper數量,默認1000
3.3 單獨處理傾斜key
如果傾斜的 key 有實際的意義,一般來講傾斜的key都很少,此時可以將它們單獨抽取出來,對應的行單獨存入臨時表中,然后打上一個較小的亂數前綴(比如0~9),最后再進行聚合,不要一個Select陳述句中,寫太多的Join,一定要了解業務,了解資料,(A0-A9)分成多條陳述句,分步執行;(A0-A4; A5-A9);先執行大表與小表的關聯;
4.兩個SQL
4.1 找出全部奪得3連貫的隊伍
team,year
活塞,1990
公牛,1991
公牛,1992
--
-- 1 排名
select team, year,
row_number() over (partition by team order by year) as rank
from t1;
-- 2 獲取分組id
select team, year,
row_number() over (partition by team order by year) as rank,
(year -row_number() over (partition by team order by year)) as groupid
from t1;
-- 3 分組求解
select team, count(1) years
from (select team,
(year -row_number() over (partition by team order by year)) as groupid
from t1
) tmp
group by team, groupid
having count(1) >= 3;
4.2 找出每個id在在一天之內所有的波峰與波谷值
波峰:
這一時刻的值 > 前一時刻的值
這一時刻的值 > 后一時刻的值
波谷:
這一時刻的值 < 前一時刻的值
這一時刻的值 < 后一時刻的值
id time price 前一時刻的值(lag) 后一時刻的值(lead)
sh66688, 9:35, 29.48 null 28.72
sh66688, 9:40, 28.72 29.48 27.74
sh66688, 9:45, 27.74
sh66688, 9:50, 26.75
sh66688, 9:55, 27.13
sh66688, 10:00, 26.30
sh66688, 10:05, 27.09
sh66688, 10:10, 26.46
sh66688, 10:15, 26.11
sh66688, 10:20, 26.88
sh66688, 10:25, 27.49
sh66688, 10:30, 26.70
sh66688, 10:35, 27.57
sh66688, 10:40, 28.26
sh66688, 10:45, 28.03
-- 思路:關鍵是找到波峰波谷的特征
-- 波峰的特征: 大于前一個時間段、后一個時間段的值
-- 波谷的特征: 小于前一個時間段、后一個時間段的值
-- 找到這個特征SQL就好寫了
select id, time, price,
case when price > beforeprice and price > afterprice then "波峰"
when price < beforeprice and price < afterprice then "波谷" end as feature
from (select id, time, price,
lag(price) over (partition by id order by time) beforeprice,
lead(price) over (partition by id order by time) afterprice
from t2
)tmp
where (price > beforeprice and price > afterprice) or
(price < beforeprice and price < afterprice);
吳邪,小三爺,混跡于后臺,大資料,人工智能領域的小菜鳥,
更多請關注

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/262848.html
標籤:其他
