Hive做爲大數據領域經常使用的數據倉庫組件,在設計和開發階段須要注意效率。影響Hive效率的不只僅是數據量過大;數據傾斜、數據冗餘、job或I/O過多、MapReduce分配不合理等因素都對Hive的效率有影響。對Hive的調優既包含對HiveQL語句自己的優化,也包含Hive配置項和MR方面的調
整。sql
從如下三個方面展開:
架構優化
參數優化
SQL優化apache
執行引擎方面針對公司內平臺的資源,選擇更合適的更快的引擎,好比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
在表的設計上優化,好比選擇分區表,分桶表,以及表的存儲格式,爲了減小數據傳輸,可使用壓縮的方式,下面給幾個參數(更多參數能夠查看官網)app
-- 中間結果壓縮 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
第二部分是參數優化,其實上面架構部分,有部分也是經過參數來控制的,這一部分的參數控制主要有下面幾個方面jvm
本地模式、嚴格模式、JVM重用、並行執行、推測執行、合併小文件、Fetch模式分佈式
當數據量較小的時候,啓動分佈式處理數據會比較慢,啓動時間較長,不如本地模式快,用下面的參數來調整oop
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 配置的 大小
這實際上是個開關,知足下面三個語句時候,就會失敗,若是不開啓就正常執行,開啓後就讓這些語句自動失敗fetch
hive.mapred.mode=nostrict -- 查詢分區表時不限定分區列的語句; -- 兩表join產生了笛卡爾積的語句; -- 用order by來排序,但沒有指定limit的語句
在mr裏面,是以進程爲單位的,一個進程就是一個Jvm,其實像短做業,這些進程可以重用就會很快,可是它的缺點是會等任務執行完畢後task插槽,這個在數據傾斜時候較爲明顯。開啓這個使用下面的參數大數據
SET mapreduce.job.jvm.numtasks=5;
Hive的查詢會轉爲stage,這些stage並非相互依賴的,能夠並行執行這些stage,使用下面的參數
SET hive.exec.parallel=true; -- 默認false SET hive.exec.parallel.thread.number=16; -- 默認8
這個參數的做用是,使用空間資源來換取獲得最終結果的時間,好比因爲網絡,資源不均等緣由,某些任務運行特別慢,會啓動備份進程處理同一份數據,並最終選用最早成功的計算結果做爲最終結果。
set mapreduce.map.speculative=true set mapreduce.reduce.speculative=true set hive.mapred.reduce.tasks.speculative.execution=true
在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;
最後一種fetch模式,則是在某些狀況下儘可能不跑mr,好比查詢幾個字段,全局查找,字段查,limit查等狀況
hive.fetch.task.conversion=more
這一部分較複雜,可能涉及到數據傾斜問題,至於數據傾斜問題一直是大數據處理的不可比避免的一個問題,處理方式也較多
sql優化是開發人員最容易控制的部分,每每是經驗使之,大約總結一下又下面的方式
列,分區拆解,sort by 代替 order by, group by 代替count(distinct) ,group by的預聚合(經過參數來控制),傾斜配置項,map join,單獨過濾空值,適當調整map 和 reduces數,這些在工做中幾乎都會碰到,儘量去優化他們呢是你要作的
這個配置與 group by 的傾斜均衡配置項殊途同歸,經過 hive.optimize.skewjoin來配置,默認false。若是開啓了,在join過程當中Hive會將計數超過閾值 hive.skewjoin.key (默認100000)的傾斜key對應的行臨時寫進文件中,而後再啓動另外一個job作map join生成結果。經過 hive.skewjoin.mapjoin.map.tasks 參數還能夠控制第二個job的mapper數量,默認1000
若是傾斜的 key 有實際的意義,通常來說傾斜的key都不多,此時能夠將它們單獨抽取出來,對應的行單獨存入臨時表中,而後打上一個較小的隨機數前綴(好比0~9),最後再進行聚合。不要一個Select語句中,寫太多的Join。必定要了解業務,瞭解數據。(A0-A9)分紅多條語句,分步執行;(A0-A4; A5-A9);先執行大表與小表的關聯;
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;
波峯:
這一時刻的值 > 前一時刻的值
這一時刻的值 > 後一時刻的值
波谷:
這一時刻的值 < 前一時刻的值
這一時刻的值 < 後一時刻的值
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);
吳邪,小三爺,混跡於後臺,大數據,人工智能領域的小菜鳥。
更多請關注