Hive用的好,才能從數據中挖掘出更多的信息來。用過hive的朋友,我想或多或少都有相似的經歷:一天下來,沒跑幾回hive,就到下班時間了。Hive在極大數據或者數據不平衡等狀況下,表現每每通常,所以也出現了presto、spark-sql等替代品。這裏重點講解hive的優化方式,例如node
優化分組:set hive.auto.convert.join=true;
優化表關聯內存運行:/*+MAPJOIN(t1,t3,t4)*/ 複製代碼
一. 錶鏈接優化python
二. 用insert into替換union all若是union all的部分個數大於2,或者每一個union部分數據量大,應該拆成多個insert into 語句,實際測試過程當中,執行時間能提高50%。示例參考以下:面試
insert overwite table tablename partition (dt= ....)
select ..... from ( select ... from A
union all
select ... from B union all select ... from C ) R
where ...;
複製代碼
能夠改寫爲:sql
insert into table tablename partition (dt= ....) select .... from A WHERE ...;
insert into table tablename partition (dt= ....) select .... from B WHERE ...;
insert into table tablename partition (dt= ....) select .... from C WHERE ...;複製代碼
三. order by & sort byorder by : 對查詢結果進行全局排序消耗時間長,須要set hive.mapred.mode=nostrictsort by : 局部排序,並不是全局有序,提升效率。apache
四. transform+python一種嵌入在hive取數流程中的自定義函數,經過transform語句能夠把在hive中不方便實現的功能在python中實現,而後寫入hive表中。示例語法以下:緩存
select transform({column names1})
using '**.py'
as {column names2}
from {table name}
複製代碼
若是除python腳本外還有其它依賴資源,可使用ADD ARVHIVE。架構
五. limit 語句快速出結果通常狀況下,Limit語句仍是須要執行整個查詢語句,而後再返回部分結果。有一個配置屬性能夠開啓,避免這種狀況—對數據源進行抽樣併發
hive.limit.optimize.enable=true --- 開啓對數據源進行採樣的功能
hive.limit.row.max.size --- 設置最小的採樣容量
hive.limit.optimize.limit.file --- 設置最大的採樣樣本數複製代碼
缺點:有可能部分數據永遠不會被處理到app
六. 本地模式對於小數據集,爲查詢觸發執行任務消耗的時間>實際執行job的時間,所以能夠經過本地模式,在單臺機器上(或某些時候在單個進程上)處理全部的任務。jvm
set oldjobtracker=${hiveconf:mapred.job.tracker};
set mapred.job.tracker=local;
set marped.tmp.dir=/home/edward/tmp;
set mapred.job.tracker=${oldjobtracker};
sql 語句
複製代碼
能夠經過設置屬性hive.exec.mode.local.auto的值爲true,來讓Hive在適當的時候自動啓動這個優化,也能夠將這個配置寫在$HOME/.hiverc文件中。當一個job知足以下條件才能真正使用本地模式:
job的輸入數據大小必須小於參數:hive.exec.mode.local.auto.inputbytes.max(默認128MB)
job的map數必須小於參數:hive.exec.mode.local.auto.tasks.max(默認4)
job的reduce數必須爲0或者1
可用參數hive.mapred.local.mem(默認0)控制child的jvm使用的最大內存數。
複製代碼
七. 並行執行Hive會將一個查詢轉化爲一個或多個階段,包括:MapReduce階段、抽樣階段、合併階段、limit階段等。默認狀況下,一次只執行一個階段。 不過,若是某些階段不是互相依賴,是能夠並行執行的。
set hive.exec.parallel=true,能夠開啓併發執行。
set hive.exec.parallel.thread.number=16; //同一個sql容許最大並行度,默認爲8。
複製代碼
會比較耗系統資源。
八. 調整mapper和reducer的個數
假設input目錄下有1個文件a,大小爲780M,那麼hadoop會將該文件a分隔成7個塊(6個128m的塊和1個12m的塊),從而產生7個map數假設input目錄下有3個文件a,b,c,大小分別爲10m,20m,130m,那麼hadoop會分隔成4個塊(10m,20m,128m,2m),從而產生4個map數。即若是文件大於塊大小(128m),那麼會拆分,若是小於塊大小,則把該文件當成一個塊。map執行時間:map任務啓動和初始化的時間+邏輯處理的時間。
減小map數如有大量小文件(小於128M),會產生多個map,處理方法是:
set mapred.max.split.size=100000000;
set mapred.min.split.size.per.node=100000000;
set mapred.min.split.size.per.rack=100000000;
複製代碼
前面三個參數肯定合併文件塊的大小,大於文件塊大小128m的,按照128m來分隔,小於128m,大於100m的,按照100m來分隔,把那些小於100m的(包括小文件和分隔大文件剩下的)進行合併。
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; – 執行前進行小文件合併。
增長map數當input的文件都很大,任務邏輯複雜,map執行很是慢的時候,能夠考慮增長Map數,來使得每一個map處理的數據量減小,從而提升任務的執行效率。set mapred.reduce.tasks=?
set mapred.reduce.tasks=?
set hive.exec.reducers.bytes.per.reducer = ?
複製代碼
通常根據輸入文件的總大小,用它的estimation函數來自動計算reduce的個數:reduce個數 = InputFileSize / bytes per reducer
九. 嚴格模式
set hive.marped.mode=strict --防止用戶執行那些可能意想不到的很差的影響的查詢
複製代碼
(1)分區表,必須選定分區範圍
(2)對於使用order by的查詢,要求必須使用limit語句。由於order by爲了執行排序過程會將全部的結果數據分發到同一個reducer中進行處理
(3)限制笛卡爾積查詢:兩張表join時必須有on語句複製代碼
十. 數據傾斜表現:任務進度長時間維持在99%(或100%),查看任務監控頁面,發現只有少許(1個或幾個)reduce子任務未完成。由於其處理的數據量和其餘reduce差別過大。單一reduce的記錄數與平均記錄數差別過大,一般可能達到3倍甚至更多。 最長時長遠大於平均時長。
緣由:
(1)key分佈不均勻
(2)業務數據自己的特性
(3)建表時考慮不周
(4)某些SQL語句自己就有數據傾斜複製代碼
解決方案:參數調節
set hive.map.aggr=true複製代碼
關注個人公衆號,後臺回覆【JAVAPDF】獲取200頁面試題!5萬人關注的大數據成神之路,不來了解一下嗎?5萬人關注的大數據成神之路,真的不來了解一下嗎?5萬人關注的大數據成神之路,肯定真的不來了解一下嗎?