大表和小表關聯查詢可以采用mapjoin優化查詢速度。
那什么是mapjoin呢?
理解MapJoin之前先介紹另一種Join方式,CommonJoin。
我們知道Hive編寫SQL語句,Hive會將SQL解析成MapReduce任務。
對於一個簡單的關聯查詢,CommonJoin任務設計Map階段和Reduce階段。
Mapper 從連接表中讀取數據並將連接的 key 和連接的 value 鍵值對輸出到中間文件中。Hadoop 在所謂的 shuffle 階段對這些鍵值對進行排序和合並。Reducer 將排序結果作為輸入,並進行實Join。Shuffle 階段代價非常昂貴,因為它需要排序和合並。
因此減少 Shuffle 和 Reduce 階段的代價可以提高任務性能。
MapJoin 的目的是減少 Shuffle和 educer階段的代價,並僅在 Map 階段進行Join。
MapJoin的工作機制如圖:
1)Task A,它是一個Local Task(在客戶端本地執行的Task),負責掃描小表b的數據,將其轉換成一個HashTable的數據結構,並寫入本地的文件中,之后將該文件加載到分布式緩存DistributeCache中。
2)Task B,該任務是一個沒有Reduce的MR,啟動MapReduce掃描大表。在Map階段,根據a的每一條記錄去和DistributeCache中的b對應的HashTable關聯,並直接輸出結果。
3)由於MapJoin沒有Reduce,所以Map直接輸出結果文件,有多少MapTask,就有多少個結果文件。
在命令行開啟MapJoin功能:
set hive.auto.convert.join=true;
Hivev0.7之前,需要使用hint提示/*+mapjoin(table)*/才會執行MapJoin。
0.7之后默認值為true,默認開啟MapJoin。
Hive能自動判斷哪個表是小表,那么多小的表才是小表呢?
由參數hive.mapjoin.smalltable.filesize=25000000決定,默認是25M。
因此小表在jion的前面和后面,效果都是一樣的,因為Hive自動判斷誰是小表,將其加載到內存。
select b.* from bigtable b join smalltable s on s.id = b.id;
select b.* from smalltable s join bigtable b on s.id = b.id;