Hive支持鏈接表的如下語法:
sql
本文主要講hive的joinapache
編寫鏈接查詢時要考慮的一些要點以下,不一樣版本支持的狀況可能會有些許不一樣:緩存
1,能夠編寫複雜的連接表達式,以下安全
SELECT a.* FROM a JOIN b ON (a.id = b.id)
SELECT a.* FROM a JOIN b ON (a.id = b.id AND a.department = b.department)
SELECT a.* FROM a LEFT OUTER JOIN b ON (a.id <> b.id)微信
2,在同一查詢中能夠鏈接兩個以上的表,例如app
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)運維
3,若是每一個表在鏈接子句中使用了相同的列,則Hive將多個表上的鏈接轉換爲單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)編輯器
上面的sql被轉換成一個map / reduce做業,由於只有b的key1列參與了鏈接。另外一方面oop
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)
上面的sql被轉換成兩個map / reduce做業,由於來自b的key1列在第一個鏈接條件中使用,而來自b的key2列在第二個鏈接條件中使用。第一個map / reduce做業與b鏈接,而後在第二個map / reduce做業中將結果與c鏈接。
4,在join的每一個map/reduce stage中,和其它被緩存的表同樣,序列中的最後一個表是經過reducer進行流式傳輸。 所以,經過組織這些表使得最大的表出如今最後一個序列中,能夠減小reducer中用於緩衝特定鏈接鍵值的行所需的內存。例如
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 做業中,表a和b的鍵的特定值的值被緩存在reducer的內存中。 而後,對於從c中檢索的每一行,都會使用緩存的行計算鏈接。
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)
一樣的上面的sql有兩個map / reduce參與計算鏈接。其中的第一個join是a和b,並緩存a的值,同時在reducers中流式傳輸b的值。其中第二個做業緩衝了第一個鏈接的結果,同時經過reducer流式傳輸c的值。
5,在每一個鏈接的map / reduce階段,能夠經過提示來指定要流式傳輸的表。例如
SELECT /*+ STREAMTABLE(a) */ a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)
全部這三個表都加入到一個map / reduce做業中,而且表b和c的鍵的特定值的值被緩存在reducer中的內存中。而後,對於從a中檢索的每一行,都會使用緩衝的行計算鏈接。若是省略了STREAMTABLE提示,則Hive會將最右邊的表加入鏈接。
6,存在LEFT,RIGHT和FULL OUTER鏈接,已提供對這些未匹配到的行在on 條件語句上的控制權。例如:
SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key)
這個查詢將返回一行中的每一行。當有一個等於a.key的b.key時,這個輸出行將是a.val,b.val,當沒有相應的b.key時,輸出行將是a.val,NULL。從沒有對應的a.key的行將被刪除。
語法「FROM LEFT OUTER JOIN b」必須寫在一行上,以便理解它是如何工做的 - a是在這個查詢中在b的左邊,因此a中的全部行都保留;
RIGHT OUTER JOIN將保留來自b的全部行,而且FULL OUTER JOIN將保留來自a和b的全部行。OUTER JOIN語義應該符合標準的SQL規範。
7,鏈接發生在where以前。所以,若是要限制鏈接的OUTPUT,則須要在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'
上面的sql將中對a和b進行鏈接,產生a.val和b.val的列表。可是,WHERE子句也能夠引用鏈接輸出中的a和b的其餘列,而後將其過濾掉。可是,每當JOIN的某行爲b找到一個鍵而沒有鍵時,b的全部列都將爲NULL,包括ds列。這就是說,你將過濾掉沒有有效的b.key的全部鏈接輸出行,所以你已經超出了你的LEFT OUTER要求。換句話說,若是在WHERE子句中引用b的任何一列,則鏈接的LEFT OUTER部分是可有可無的。相反,當外部鏈接時,使用下面的語法:
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')
結果是鏈接的輸出被預先過濾,而且您將不會獲得有一個有效的a.key但沒有匹配的b.key行的後過濾的麻煩。相同的邏輯適用於右和全鏈接。
8,鏈接不可交換!鏈接是左關聯的,不管它們是左或右鏈接。
SELECT a.val1, a.val2, b.val, c.val
FROM a
JOIN b ON (a.key = b.key)
LEFT OUTER JOIN c ON (a.key = c.key)
首先對a和b進行join,丟棄在其餘表中沒有a相應的鍵的a或b中的全部內容。而後將減少後的表跟c表進行join。這提供了不直觀的結果,若是在a和c中都存在一個鍵,但b中不存在:整個行(包括a.val1,a.val2和a.key)在「a JOIN b」步驟中被刪除,由於它不在b中存在。結果沒有a.key,因此當它與c進行 LEFT OUTER JOIN的時候,c.val被刪除了,由於沒有與a.key相匹配的c.key(由於a的那一行被刪除了)。一樣,若是這是一個RIGHT OUTER JOIN(而不是LEFT),咱們最終會獲得一個更奇怪的效果:NULL,NULL,NULL,c.val,由於即便咱們指定了a.key = c.key做爲鏈接鍵,咱們刪除了與第一個JOIN不匹配的全部行。
爲了達到更直觀的效果,咱們應該改成 FROM c LEFT OUTER JOIN a ON (c.key = a.key) LEFT OUTER JOIN b ON (c.key = b.key).
9,LEFT SEMI JOIN以有效的方式實現不相關的IN / EXISTS子查詢語義。從Hive 0.13開始,使用子查詢支持IN / NOT IN / EXISTS / NOT EXISTS運算符,所以大多數這些JOIN沒必要手動執行。使用LEFT SEMI 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)
10,若是除了一個鏈接的表以外的全部表都很小,則鏈接能夠做爲僅map工做來執行。
SELECT /*+ MAPJOIN(b) */ a.key, a.value
FROM a JOIN b ON a.key = b.key
上面的查詢不須要reduce。對於每一個mapper,a,b都被徹底讀取。限制是不能執行FULL / RIGHT OUTER JOIN b。
11,若是被鏈接的表在鏈接列上被分桶,而且一個表中的桶的數量是另外一個表中的桶的數量的倍數,則桶能夠彼此鏈接。若是表A有4個桶,而表B有4個桶,則下列聯接
SELECT /*+ MAPJOIN(b) */ a.key, a.value
FROM A a JOIN B b ON a.key = b.key
僅僅在mapper上便可完成鏈接完成。不是爲每一個A的mapper去徹底獲取B,而只是獲取所需的桶。對於上面的查詢,A的映射器處理存儲桶1將僅取出B的桶1.它不是默認的行爲,可使用如下參數使能:
set hive.optimize.bucketmapjoin = true
12,若是鏈接的表在鏈接列上進行排序和分桶,而且具備相同數量的存儲桶,則能夠執行sort-merge鏈接。相應的桶在mapper上相互鏈接。若是A和B都有4個桶,
SELECT /*+ MAPJOIN(b) */ a.key, a.value
FROM A a JOIN B b ON a.key = b.key
上面的功能盡在mapper便可完成。A的桶的映射器將遍歷B的相應桶。這不是默認行爲,須要設置如下參數:
set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
set hive.optimize.bucketmapjoin = true;
set hive.optimize.bucketmapjoin.sortedmerge = true;
若有疑問請參考官方連接
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Joins
對於hive不一樣版本join的不支持狀況,浪尖這裏給出以下官方截圖,:
推薦閱讀:
1,hive安裝部署
2,Hive : SORT BY vs ORDER BY vs DISTRIBUTE BY vs CLUSTER BY
關於Spark學習技巧
kafka,hbase,spark,Flink等入門到深刻源碼,spark機器學習,大數據安全,大數據運維,請關注浪尖公衆號,看高質量文章。
更多文章,敬請期待
本文分享自微信公衆號 - 浪尖聊大數據(bigdatatip)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。