HIVE 筆記
1. 如果join中多個表的 join key 是同一個,則 join 會被轉化為單個 map/reduce 任務,例如:
SELECT a.val, b.val, c.val FROM a JOIN b
ON (a.key = b.key1) JOIN c
ON (c.key = b.key1)
被轉化為單個 map/reduce 任務,因為 join 中只使用了 b.key1 作為 join key。
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1)
JOIN c ON (c.key = b.key2)
而這一 join 被轉化為 2 個 map/reduce 任務。因為 b.key1 用於第一次 join 條件,而 b.key2 用於第二次 join。
2. join 時,每次 map/reduce 任務的邏輯:
reducer 會快取 join 序列中除了最後一個表的所有表的記錄,再透過最後一個表將結果序列化到檔案系統。這一實現有助於在 reduce 端減少記憶體的使用量。實踐中,應該把最大的那個表寫在最後(否則會 因為快取浪費大量記憶體)。例如:
SELECT a.val, b.val, c.val FROM a
JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)
所有表都使用同一個 join key(使用 1 次 map/reduce 任務計算)。Reduce 端會快取 a 表和 b 表的記錄,然後每次取得一個 c 表的記錄就計算一次 join 結果,類似的還有:
SELECT a.val, b.val, c.val FROM a
JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)
這裡用了 2 次 map/reduce 任務。第一次快取 a 表,用 b 表 ;第二次快取第一次 map/reduce 任務的結果,然後用 c 表序列化。3. Join 發生在 WHERE 子句之前。如果你想限制 join 的輸出,應該在 WHERE 子句中寫過濾條件——或是在 join 子句中寫。這裡面一個容易混淆的問題是表分割槽的情況:
SELECT a.val, b.val FROM a
LEFT OUTER JOIN b ON (a.key=b.key)
WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'
會 join a 表到 b 表(OUTER JOIN),列出 a.val 和 b.val 的記錄。WHERE 從句中可以使用其他列作為過濾條件。但是,如前所述,如果 b 表中找不到對應 a 表的記錄,b 表的所有列都會列出 NULL,包括 ds 列。也就是說,join 會過濾 b 表中不能找到匹配 a 表 join key 的所有記錄。這樣的話,LEFT OUTER 就使得查詢結果與 WHERE 子句無關了。解決的辦法是在 OUTER JOIN 時使用以下語法:
SELECT a.val, b.val FROM a LEFT OUTER JOIN b
ON (a.key=b.key AND
b.ds='2009-07-07' AND
a.ds='2009-07-07')
這一查詢的結果是預先在 join 階段過濾過的,所以不會存在上述問題。這一邏輯也可以應用於 RIGHT 和 FULL 型別的 join 中。
4. 是 IN/EXISTS 子查詢的一種更高效的實現。Hive 當前沒有實現 IN/EXISTS 子查詢,所以你可以用 LEFT SEMI JOIN 重寫你的子查詢語句。LEFT SEMI JOIN 的限制是, JOIN 子句中右邊 的表只能在 ON 子句中設定過濾條件,在 WHERE 子句、SELECT 子句或其他地方過濾都不行。
SELECT a.key, a.value
FROM a
WHERE a.key in (SELECT b.key FROM B);
可以被重寫為:
SELECT a.key, a.val
FROM a LEFT
SEMI JOIN b on (a.key = b.key)
5. SQL標準中,任何對null的操作(數值比較,字串操作等)結果都為null。Hive對null值處理的邏輯和標準基本一致,除了Join時的特殊邏輯。
這裡的特殊邏輯指的是,Hive的Join中,作為Join key的欄位比較,null=null是有意義的,且返回值為true。檢查以下查詢:
select u.uid, count(u.uid)
from t_weblog l join t_user u on (l.uid = u.uid) group by u.uid;
查詢中,t_weblog表中uid為空的記錄將和t_user表中uid為空的記錄做連線,即l.uid = u.uid=null成立。
如果需要與標準一致的語義,我們需要改寫查詢手動過濾null值的情況:
select u.uid, count(u.uid)
from t_weblog l join t_user u
on (l.uid = u.uid and l.uid is not null and u.uid is not null)
group by u.uid;
實踐中,這一語義區別也是經常導致資料傾斜的原因之一。
6. count(distinct
),在資料量大的情況下,效率較低,如果是多count(distinct
)效率更低,因為count(distinct)是按group
by 欄位分組,按distinct欄位排序,
一般這種分佈方式是很傾斜的,比如男uv,女uv,淘寶一天30億的pv,如果按性別分組,分配2個reduce,每個reduce處理15億資料。
7. Order by 能夠預期產生完全排序的結果,但是它是透過只用一個reduce來做到這點的。所以對於大規模的資料集它的效率非常低。在很多情況下,並不需要全域性排序,此時可以換成Hive的非標準擴充套件sort by。Sort by為每個reducer產生一個排序檔案。在有些情況下,你需要控制某個特定行應該到哪個reducer,通常是為了進行後續的聚集操作。Hive的distribute by 子句可以做這件事
From record2
select year, temperature
distribute by year
sort by year asc, temperature desc;
8. 合併mapreduce操作
Multi-group by是Hive的一個非常好的特性,它使得Hive中利用中間結果變得非常方便。例如:
FROM (SELECT a.status, b.school, b.gender
FROM status_updates a JOIN profiles
b
ON (a.userid = b.userid and a.ds='2009-03-20' )
) subq1
INSERT OVERWRITE TABLE gender_summary PARTITION(ds='2009-03-20')
SELECT subq1.gender, COUNT(1) GROUP BY subq1.gender
INSERT OVERWRITE TABLE school_summary PARTITION(ds='2009-03-20')
SELECT subq1.school, COUNT(1) GROUP BY subq1.school
上述查詢語句使用了Multi-group by特性連續group by了2次資料,使用不同的group
by key。這一特性可以減少一次MapReduce操作。
9. 空值資料傾斜問題:
解決方法1: user_id為空的不參與關聯
Select * From log a
Join bmw_users b
On a.user_id is not null
And a.user_id = b.user_id
Union all
Select * from log a
where a.user_id is null;
解決方法2 :賦與空值分新的key值
Select *
from log a
left outer join bmw_users b
on case when a.user_id is null then concat(‘dp_hive’,rand() ) else a.user_id end = b.user_id;
結論:方法2比方法效率更好,不但io少了,而且作業數也少了。方法1 log讀取兩次,jobs是2。方法2 job數是1 。這個最佳化適合無效id(比如-99,’’,null等)產生的傾斜問題。把空值的key變成一個字串 加上隨機數,就能把傾斜的資料分到不同的reduce上 ,解決資料傾斜問題。附上hadoop通用關聯的實現方法(關聯透過二次排序實現的,關聯的列為parition key,關聯的列c1和表的tag組成排序的group key,根據parition key分配reduce。同一reduce內根據group key排序)
10. 不同資料型別關聯的資料傾斜
場景:一張表s8的日誌,每個商品一條記錄,要和商品表關聯。但關聯卻碰到傾斜的問題。s8的日誌中有字串商品id,也有數字的商品id,型別是string的,但商品中的數字id是bigint的。猜測問題的原 因 是把s8的商品id轉成數字id做hash來分配reduce,所以字串id的s8日誌,都到一個reduce上了,解決的方法驗證了這個猜測。
解決方法:把數字型別轉換成字串型別
Select * from s8_log a
Left outer join r_auction_auctions b
On a.auction_id = cast(b.auction_id as string);
11. 合併小檔案
檔案數目過多,會給 HDFS 帶來壓力,並且會影響處理效率,可以透過合併 Map 和 Reduce 的結果檔案來消除這樣的影響:
hive.merge.mapfiles = true 是否和並 Map 輸出檔案,預設為 True
hive.merge.mapredfiles = false 是否合併 Reduce 輸出檔案,預設為 False
hive.merge.size.per.task = 256*1000*1000 合併檔案的大小
12.資料傾斜解決:
原語句:
如果欄位ext_field7為空不需要關聯:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29754888/viewspace-1315701/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- hive學習筆記Hive筆記
- Hive學習筆記 1 Hive體系結構Hive筆記
- Hive學習筆記 6 Hive的JDBC連線Hive筆記JDBC
- Hive1.2.1安裝筆記Hive筆記
- Hive學習筆記 2 Hive的資料型別Hive筆記資料型別
- Hive學習筆記 4 Hive的資料匯入Hive筆記
- hive學習筆記之十一:UDTFHive筆記
- Hive學習筆記 5 Hive的資料查詢、函式Hive筆記函式
- hive學習筆記之五:分桶Hive筆記
- hive學習筆記之八:SqoopHive筆記OOP
- hive3.0.0的一些筆記Hive筆記
- Hive學習筆記:基礎語法Hive筆記
- HIVE隨手記——Hive命令(?$HIVE_HOME/bin/hive)Hive
- hive學習筆記之九:基礎UDFHive筆記
- hive學習筆記之四:分割槽表Hive筆記
- hive學習筆記之六:HiveQL基礎Hive筆記
- hive學習筆記之七:內建函式Hive筆記函式
- 大資料學習筆記(十三)-Hive高階大資料筆記Hive
- Hive學習筆記 ---- 支援Update和Delete以及MergeHive筆記delete
- hive學習筆記之一:基本資料型別Hive筆記資料型別
- Hadoop學習筆記—17.Hive框架學習Hadoop筆記Hive框架
- hive學習筆記之三:內部表和外部表Hive筆記
- Hive學習筆記 3 Hive的資料模型:內部表、分割槽表、外部表、桶表、檢視Hive筆記模型
- hive on tez踩坑記2-hive0.14 on tez薦Hive
- Hive隨手記——建庫Hive
- hive on spark記憶體模型HiveSpark記憶體模型
- hive學習筆記之十:使用者自定義聚合函式(UDAF)Hive筆記函式
- Hive入門學習隨筆(二)Hive
- hive編寫udf實踐記錄Hive
- hive原始碼編譯(失敗記錄)Hive原始碼編譯
- [Hive]Hive排序優化Hive排序優化
- Hive --------- hive 的優化Hive優化
- Hive之 hive架構Hive架構
- [hive] hive cli 命令列Hive命令列
- 【Hive】hive資料遷移Hive
- Hive篇--搭建Hive叢集Hive
- Hive篇---Hive使用優化Hive優化
- 印象筆記 --- 方法分享筆記筆記