您好,登錄后才能下訂單哦!
這篇文章主要介紹“Hadoop中的兩表是什么”,在日常操作中,相信很多人在Hadoop中的兩表是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Hadoop中的兩表是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
Common Join
最為普通的join策略,不受數據量的大小影響,也可以叫做reduce side join ,最沒效率的一種join 方式. 它由一個mapreduce job 完成.
首先將大表和小表分別進行map 操作, 在map shuffle 的階段每一個map output key 變成了table_name_tag_prefix + join_column_value , 但是在進行partition 的時候它仍然只使用join_column_value 進行hash.
每一個reduce 接受所有的map 傳過來的split , 在reducce 的shuffle 階段,它將map output key 前面的table_name_tag_prefix 給舍棄掉進行比較. 因為reduce 的個數可以由小表的大小進行決定,所以對于每一個節點的reduce 一定可以將小表的split 放入內存變成hashtable. 然后將大表的每一條記錄進行一條一條的比較.
Map Join
Map Join 的計算步驟分兩步,將小表的數據變成hashtable廣播到所有的map 端,將大表的數據進行合理的切分,然后在map 階段的時候用大表的數據一行一行的去探測(probe) 小表的hashtable. 如果join key 相等,就寫入HDFS.
map join 之所以叫做map join 是因為它所有的工作都在map 端進行計算.
hive 在map join 上做了幾個優化:
hive 0.6 的時候默認認為寫在select 后面的是大表,前面的是小表, 或者使用 /*+mapjoin(map_table) */ 提示進行設定. hive 0.7 的時候這個計算是自動化的,它首先會自動判斷哪個是小表,哪個是大表,這個參數由(hive.auto.convert.join=true)來控制. 然后控制小表的大小由(hive.smalltable.filesize=25000000L)參數控制(默認是25M),當小表超過這個大小,hive 會默認轉化成common join. 你可以查看HIVE-1642.
首先小表的Map 階段它會將自己轉化成MapReduce Local Task ,然后從HDFS 取小表的所有數據,將自己轉化成Hashtable file 并壓縮打包放入DistributedCache 里面.
目前hive 的map join 有幾個限制,一個是它打算用BloomFilter 來實現hashtable , BloomFilter 大概比hashtable 省8-10倍的內存, 但是BloomFilter 的大小比較難控制.
現在DistributedCache 里面hashtable默認的復制是3份,對于一個有1000個map 的大表來說,這個數字太小,大多數map 操作都等著DistributedCache 復制.
Bucket Map Join
hive 建表的時候支持hash 分區通過指定clustered by (col_name,xxx ) into number_buckets buckets 關鍵字.
當連接的兩個表的join key 就是bucket column 的時候,就可以通過
hive.optimize.bucketmapjoin= true
來控制hive 執行bucket map join 了, 需要注意的是你的小表的number_buckets 必須是大表的倍數. 無論多少個表進行連接這個條件都必須滿足.(其實如果都按照2的指數倍來分bucket, 大表也可以是小表的倍數,不過這中間需要多計算一次,對int 有效,long 和string 不清楚)
Bucket Map Join 執行計劃分兩步,第一步先將小表做map 操作變成hashtable 然后廣播到所有大表的map端,大表的map端接受了number_buckets 個小表的hashtable并不需要合成一個大的hashtable,直接可以進行map 操作,map 操作會產生number_buckets 個split,每個split 的標記跟小表的hashtable 標記是一樣的, 在執行projection 操作的時候,只需要將小表的一個hashtable 放入內存即可,然后將大表的對應的split 拿出來進行判斷,所以其內存限制為小表中最大的那個hashtable 的大小.
Bucket Map Join 同時也是Map Side Join 的一種實現,所有計算都在Map 端完成,沒有Reduce 的都被叫做Map Side Join ,Bucket 只是hive 的一種hash partition 的實現,另外一種當然是值分區.
create table a (xxx) partition by (col_name)
不過一般hive 中兩個表不一定會有同一個partition key, 即使有也不一定會是join key. 所以hive 沒有這種基于值的map side join, hive 中的list partition 主要是用來過濾數據的而不是分區. 兩個主要參數為(hive.optimize.cp = true 和 hive.optimize.pruner=true)
hadoop 源代碼中默認提供map side join 的實現, 你可以在hadoop 源碼的src/contrib/data_join/src 目錄下找到相關的幾個類. 其中TaggedMapOutput 即可以用來實現hash 也可以實現list , 看你自己決定怎么分區. Hadoop Definitive Guide 第8章關于map side join 和side data distribution 章節也有一個例子示例怎樣實現值分區的map side join.
Sort Merge Bucket Map Join
Bucket Map Join 并沒有解決map join 在小表必須完全裝載進內存的限制, 如果想要在一個reduce 節點的大表和小表都不用裝載進內存,必須使兩個表都在join key 上有序才行,你可以在建表的時候就指定sorted by join key 或者使用index 的方式.
set hive.optimize.bucketmapjoin = true;
set hive.optimize.bucketmapjoin.sortedmerge = true;
set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
Bucket columns == Join columns == sort columns
這樣小表的數據可以每次只讀取一部分,然后還是用大表一行一行的去匹配,這樣的join 沒有限制內存的大小. 并且也可以執行全外連接.
Skew Join
真實數據中數據傾斜是一定的, hadoop 中默認是使用
hive.exec.reducers.bytes.per.reducer = 1000000000
也就是每個節點的reduce 默認是處理1G大小的數據,如果你的join 操作也產生了數據傾斜,那么你可以在hive 中設定
set hive.optimize.skewjoin = true;
set hive.skewjoin.key = skew_key_threshold (default = 100000)
hive 在運行的時候沒有辦法判斷哪個key 會產生多大的傾斜,所以使用這個參數控制傾斜的閾值,如果超過這個值,新的值會發送給那些還沒有達到的reduce, 一般可以設置成你
(處理的總記錄數/reduce個數)的2-4倍都可以接受.
傾斜是經常會存在的,一般select 的層數超過2層,翻譯成執行計劃多于3個以上的mapreduce job 都很容易產生傾斜,建議每次運行比較復雜的sql 之前都可以設一下這個參數. 如果你不知道設置多少,可以就按官方默認的1個reduce 只處理1G 的算法,那么 skew_key_threshold = 1G/平均行長. 或者默認直接設成250000000 (差不多算平均行長4個字節)
Left Semi Join
hive 中沒有in/exist 這樣的子句,所以需要將這種類型的子句轉成left semi join. left semi join 是只傳遞表的join key給map 階段 , 如果key 足夠小還是執行map join, 如果不是則還是common join.
join 策略中的難點
大多數只適合等值連接(equal join) ,
范圍比較和全外連接沒有合適的支持
提前分區,零時分區,排序,多種不同執行計劃很難評價最優方案.
沒有考慮IO 比如臨時表,網絡消耗和網絡延遲時間,CPU時間,
最優的方案不代表系統資源消耗最少.
到此,關于“Hadoop中的兩表是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。