在闡述Hive Join具體的優化方法之前,首先看一下Hive Join的幾個重要特點,在實際使用時也可以利用下列特點做相應優化:
1. 只支持等值連接
2. 底層會將寫的HQL語句轉換為MapReduce,並且reduce會將join語句中除最后一個表外都緩存起來
3. 當三個或多個以上的表進行join操作時,如果每個on使用相同的字段連接時只會產生一個mapreduce
具體的優化建議:
1. 合理的設置map和reduce數量
jvm重用。可在hadoop的mapred-site.xml中設置jvm被重用的次數,參數mapred.job.reuse.jvm.num.tasks
2. 對於任務重沒有依賴關系的階段開啟並發執行,設置屬性:set hive.exec.parallel=true
3. 查詢分區表時,在查詢條件中指定分區
4. 盡量使用left semi join 替代in、not in、exists
因為left semi join在執行時,對於左表中指定的一條記錄,一旦在右表中找到立即停止掃描,效率更高
5. 當多個表進行查詢時,從左到右表的大小順序應該是從小到大。原因:hive在對每行記錄操作時會把其他表先緩存起來,直到掃描最后的表進行計算
6. 對於經常join的表,針對join字段進行分桶,這樣在join時不必全表掃描
7. 小表進行mapjoin
如果在join的表中,有一張表數據量較小,可以存於內存中,這樣該表在和其他表join時可以直接在map端進行,省掉reduce過程,效率高。設置方式主要分兩種:
1)自動方式
set hive.auto.convert.join=true;hive.mapjoin.smalltable.filesize,設置可以mapjoin的表的大小,默認值是25Mb
2)手動方式
select /*+ mapjoin(A)*/ x.a, y.b from t_x x join t_y y on x.id=y.id;
8. 同一種數據的多種處理:從一個數據源產生的多個數據聚合,無需每次聚合都需要重新掃描一次。
例如:任務重需要執行insert overwrite table t_y select * from t_x;和
insert overwrite table t_z select * from t_x;
可以優化成:from t_x insert overwrite table t_y select * insert overwrite table t_z select *
9. join中的數據傾斜處理
set hive.optimize.skewjoin=true;
set hive.skewjoin.key=100000;
當單個reduce節點處理數據閾值,會進行skewjoin,建議設置為平均數據量的2-4倍。
原理:會產生兩個job,第一個job會將超過hive.skewjoin.key設置值的記錄的key加上一些隨機數,將這些相同的key打亂,然后分配到不同的節點上面進行計算。最后再啟動一個job,在第一個job處理的基礎上(即第一個job的reduce輸出結果)再進行處理,將相同的key分發到相同的節點上處理。因為會產生兩個job進行處理,在實際使用中還是要注意以及閾值的設置。
10. limit調優
limit語句通常是執行整個語句后返回部分結果。但通過設置參數set hive.limit.optimize.enable=true,將針對查詢對元數據進行抽樣。同時可能還需要設置以下兩個參數:
set hive.limit.row.max.size=10000;設置最小的采樣容量
set hive.limit.optimize.limit.file=20;設置最大的采樣樣本數
這種優化方式存在一個缺點:有可能部分數據永遠不會被處理到
關注微信公眾號:大數據學習與分享,獲取更對技術干貨