(1)核心思想:把Hive SQL 當做Mapreduce程序去優化
(2)以下SQL不會轉爲Mapreduce來執行
- select僅查詢本表字段
- where僅對本表字段做條件過濾
(3)Explain 顯示執行計劃:EXPLAIN [EXTENDED] query
(4)Hive抓取策略:Hive中對某些情況的查詢不需要使用MapReduce計算
(5)抓取策略 :Set hive.fetch.task.conversion=none/more;
(6)Hive運行方式:本地模式、集羣模式
本地模式:
開啓本地模式:set hive.exec.mode.local.auto=true;
注意:
- hive.exec.mode.local.auto.inputbytes.max默認值爲128M
- 表示加載文件的最大值,若大於該配置仍會以集羣方式來運行!
(7)並行計算
通過設置以下參數開啓並行模式:set hive.exec.parallel=true;
注意:hive.exec.parallel.thread.number(一次SQL計算中允許並行執行的job個數的最大值)
(8)嚴格模式
通過設置以下參數開啓嚴格模式:set hive.mapred.mode=strict;(默認爲:nonstrict非嚴格模式)
查詢限制:
1、對於分區表,必須添加where對於分區字段的條件過濾;
2、order by語句必須包含limit輸出限制;
3、限制執行笛卡爾積的查詢。
(9)Hive排序優化
Order By - 對於查詢結果做全排序,只允許有一個reduce處理
(當數據量較大時,應慎用。嚴格模式下,必須結合limit來使用)
Sort By - 對於單個reduce的數據進行排序
Distribute By - 分區排序,經常和Sort By結合使用
Cluster By - 相當於 Sort By + Distribute By
(Cluster By不能通過asc、desc的方式指定排序規則;
可通過 distribute by column sort by column asc|desc 的方式)
(10)Hive Join優化
Join計算時,將小表(驅動表)放在join的左邊
Map Join:在Map端完成Join:
兩種實現方式:
1、SQL方式,在SQL語句中添加MapJoin標記(mapjoin hint)
語法:
SELECT /*+ MAPJOIN(smallTable) */ smallTable.key, bigTable.value
FROM smallTable JOIN bigTable ON smallTable.key = bigTable.key;
2、開啓自動的MapJoin
自動的map join:
通過修改以下配置啓用自動的mapjoin:set hive.auto.convert.join = true;(該參數爲true時,Hive自動對左邊的表統計量,如果是小表就加入內存,即對小表使用Map join)
相關配置參數:
hive.mapjoin.smalltable.filesize;
(大表小表判斷的閾值,如果表的大小小於該值則會被加載到內存中運行)
hive.ignore.mapjoin.hint;
(默認值:true;是否忽略mapjoin hint 即mapjoin標記)
hive.auto.convert.join.noconditionaltask;
(默認值:true;將普通的join轉化爲普通的mapjoin時,是否將多個mapjoin轉化爲一個mapjoin)
hive.auto.convert.join.noconditionaltask.size;
(將多個mapjoin轉化爲一個mapjoin時,其表的最大值)
儘可能使用相同的連接鍵(會轉化爲一個MapReduce作業)
大表join大表:
空key過濾:有時join超時是因爲某些key對應的數據太多,而相同key對應的數據都會發送到相同的reducer上,從而導致內存不夠。此時我們應該仔細分析這些異常的key,很多情況下,這些key對應的數據是異常數據,我們需要在SQL語句中進行過濾。
空key轉換:有時雖然某個key爲空對應的數據很多,但是相應的數據不是異常數據,必須要包含在join的結果中,此時我們可以表a中key爲空的字段賦一個隨機的值,使得數據隨機均勻地分不到不同的reducer上
(11)Map-Side聚合
通過設置以下參數開啓在Map端的聚合:set hive.map.aggr=true;
相關配置參數:
hive.groupby.mapaggr.checkinterval:
map端group by執行聚合時處理的多少行數據(默認:100000)
hive.map.aggr.hash.min.reduction:
進行聚合的最小比例(預先對100000條數據做聚合,若聚合之後的數據量/100000的值大於該配置0.5,則不會聚合)
hive.map.aggr.hash.percentmemory:
map端聚合使用的內存的最大值
hive.map.aggr.hash.force.flush.memory.threshold:
map端做聚合操作是hash表的最大可用內容,大於該值則會觸發flush
hive.groupby.skewindata
是否對GroupBy產生的數據傾斜做優化,默認爲false
(12)合併小文件
文件數目小,容易在文件存儲端造成壓力,給hdfs造成壓力,影響效率
設置合併屬性:
是否合併map輸出文件:hive.merge.mapfiles=true
是否合併reduce輸出文件:hive.merge.mapredfiles=true;
合併文件的大小:hive.merge.size.per.task=256*1000*1000
去重統計:
數據量小的時候無所謂,數據量大的情況下,由於COUNT DISTINCT操作需要用一個Reduce Task來完成,這一個Reduce需要處理的數據量太大,就會導致整個Job很難完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替換
(13)Hive - JVM重用
適用場景:
1、小文件個數過多
2、task個數過多
通過 set mapred.job.reuse.jvm.num.tasks=n; 來設置(n爲task插槽個數)
缺點:設置開啓之後,task插槽會一直佔用資源,不論是否有task運行,直到所有的task即整個job全部執行完成時,纔會釋放所有的task插槽資源!