一、概述
Hive是一個基于Hadoop的數據倉庫解決方案,它提供了類似于SQL的查詢語言,稱為HiveQL,用于處理結構化數據。在Hive中,JOIN操作用于將兩個或多個表中的數據連接在一起,以便進行聯合查詢和分析。
Hive 中 的 Join 可分為 Common Join(Reduce階段完成join)和 Map Join(Map 階段完成 join)。
Hive中的JOIN操作是通過MapReduce或Tez任務來執行的,具體的執行過程如下:
- 數據分片:Hive將參與JOIN操作的表按照指定的JOIN條件進行分片。每個分片是表的一個子集,用于并行處理。
- Map階段:在Map階段,Hive會為每個分片創建一個Map任務,并從輸入數據中提取JOIN條件所需要的鍵值對。對于每個鍵值對,Hive會將鍵發送到對應的Reducer節點,并將值存儲在中間緩存中。
- Shuffle階段:在Shuffle階段,Hive將具有相同鍵的鍵值對發送到相同的Reducer節點。這個過程稱為數據洗牌,它確保具有相同鍵的數據被發送到同一個Reducer節點進行處理。
- Reduce階段:在Reduce階段,Hive會為每個Reducer節點創建一個Reduce任務。每個Reduce任務接收來自不同MApper節點的具有相同鍵的鍵值對,并執行JOIN操作。在JOIN操作中,Hive會根據JOIN條件將具有相同鍵的記錄組合在一起,生成JOIN結果。
【注意】Hive中的JOIN操作是通過兩個或多個表的列進行連接的。JOIN條件指定了哪些列用于匹配。Hive支持多種類型的JOIN,包括INNER JOIN(內連接)、LEFT JOIN(左連接)、RIGHT JOIN(右連接)和FULL JOIN(全連接),可以根據需要選擇適當的JOIN類型。
此外,Hive還提供了一些優化技術來提高JOIN操作的性能,例如對表進行分區和對中間結果進行壓縮。這些技術可以減少數據移動和存儲開銷,加快JOIN操作的執行速度。
【總結】Hive中的JOIN操作通過MapReduce或Tez任務進行執行,包括數據分片、Map階段、Shuffle階段和Reduce階段。它使用JOIN條件將具有相同鍵的記錄組合在一起,生成JOIN結果。通過選擇適當的JOIN類型和使用優化技術,可以提高JOIN操作的性能。
二、環境準備
如果已經有了環境了,可以忽略,如果想快速部署環境可以參考我這篇文章:通過 Docker-compose 快速部署 Hive 詳細教程
# 登錄容器
docker exec -it hive-hiveserver2 bash
# 連接hive
beeline -u jdbc:hive2://hive-hiveserver2:10000 -n hadoop
三、Hive JOIN 類型
Hive是一個基于Hadoop的數據倉庫工具,用于處理大規模數據集。在Hive中,JOIN是一種常用的操作,用于將兩個或多個表中的數據按照指定的條件進行關聯。
Hive支持多種JOIN類型,包括:
- 內連接(inner join 或者簡寫成 join):只返回兩個表中匹配的行。內連接基于一個或多個條件(通常是相等條件),匹配兩個表中的行,并將匹配的行返回為結果。只有滿足條件的行才會被包含在結果中。
示例:
SELECT *
FROM table1
JOIN table2
ON table1.id = table2.id;
- 左外連接(left outer join 或者簡寫成 left join):返回左表中的所有行以及與右表匹配的行。如果右表中沒有匹配的行,則對應的結果列將包含NULL值。
示例:
SELECT *
FROM table1
LEFT JOIN table2
ON table1.id = table2.id;
- 右外連接(right outer join 或者簡寫成 right join):返回右表中的所有行以及與左表匹配的行。如果左表中沒有匹配的行,則對應的結果列將包含NULL值。
示例:
SELECT *
FROM table1
RIGHT JOIN table2
ON table1.id = table2.id;
- 全外連接(full outer join 或者簡寫成 full join):返回兩個表中的所有行,如果某一行在另一個表中沒有匹配,則對應的結果列將包含NULL值。
SELECT *
FROM table1
FULL OUTER JOIN table2
ON table1.id = table2.id;
這些JOIN類型可以根據具體的業務需求選擇適當的類型。在Hive中,可以使用JOIN關鍵字來執行JOIN操作,并指定要連接的表以及連接條件。例如,使用"INNER JOIN"、"LEFT OUTER JOIN"、"RIGHT OUTER JOIN"、"FULL OUTER JOIN"等來指定JOIN類型。
根據具體的需求和數據情況,你可以選擇不同的JOIN類型來滿足查詢需求。
四、Map,Shuffle,Reduce三階段
MapReduce的全套過程分為三個大階段,分別是Map、Shuffle和Reduce。結合多篇資料,我最終確定劃分11個小步驟來描述這個過程,在后續的內容中我也會結合一部分源碼來進行剖析。
1)Map 階段
在Map階段,原始數據被分割成多個大小相同的數據塊,每個數據塊被分配給一個Map任務處理。Map任務將輸入數據轉化為一系列鍵值對,其中鍵是進行處理的對象,值是相關聯的數據。Map階段的輸出結果被保存在本地磁盤上,等待Shuffle階段的處理。
2)Shuffle階段
在Shuffle階段,Map任務的輸出結果根據鍵被分配到不同的Reduce任務進行處理。這個過程稱為Shuffle過程。具體來說,每個Map任務會將其輸出結果按照鍵的哈希值分發到多個節點,每個節點對應一個Reduce任務。在Shuffle過程中,數據通過網絡傳輸,需要考慮網絡帶寬和網絡延遲等因素,以確保數據能夠及時地到達目標節點。
3)Reduce階段
在Reduce階段,每個Reduce任務將接收到的鍵值對根據鍵進行聚合或者排序等操作,然后生成最終的輸出結果。同樣,在Reduce階段的輸出結果會被保存在本地磁盤上,最終匯總成最終的輸出結果。
【總結】可以看出,MapReduce框架中的三個階段都是分布式的,可以在多臺計算機上并行運行。MapReduce框架能夠有效地處理大規模數據,并實現高效的分布式計算。由于MapReduce框架的通用性和可伸縮性,因此已經被廣泛應用于各種數據處理和機器學習任務。
五、Common Join(Reduce階段)
在Hive中,常見連接(Common Join)在Reduce階段進行。當執行常見連接時,Hive會首先對參與連接的表進行Map階段的處理,將數據按照連接條件進行分組和排序,并將它們發送到不同的Reduce任務中。
- 在Reduce階段,每個Reduce任務會接收來自不同表的分組數據,并執行連接操作。具體而言,Reduce任務會對具有相同連接鍵的記錄進行配對,從而實現連接操作。這通常涉及將具有相同連接鍵的記錄組合在一起,以生成最終的連接結果。
- 在Reduce階段,Hive使用MapReduce框架來執行常見連接操作。它通過將相同連接鍵的數據分發到相同的Reduce任務中,實現數據的匹配和連接。這種分布式計算的方式可以有效地處理大規模數據集,并實現高效的連接操作。
需要注意的是,由于常見連接操作在Reduce階段進行,所以在執行大規模連接操作時,可能會產生大量的中間數據和計算開銷。因此,優化連接操作的性能是一個重要的考慮因素,可以通過調整Hive的配置參數、選擇適當的連接算法等方式來改善連接操作的性能。
以下面的HQL為例,圖解其過程:
SELECT a.id,a.dept,b.age
FROM a join b
ON (a.id = b.id);
六、Map Join(Map 階段)
Map Join 通常用于一個很小的表和一個大表進行 join 的場景,具體小表有多小,由參數hive.mapjoin.smalltable.filesize 來決定,默認值為 25M。滿足條件的話 Hive 在執行時候會自動轉化為 MapJoin,或使用 hint 提示 /*+ mapjoin(table) */ 執行 MapJoin。
如上圖中的流程:
- 首先 Task A 在客戶端本地執行,負責掃描小表 b 的數據,將其轉換成一個HashTable 的數據結構,并寫入本地的文件中,之后將該文件加載到 DistributeCache 中。
- 接下來的 Task B 任務是一個沒有 Reduce 的 MapReduce,啟動 MapTasks 掃描大表 a,在 Map 階段,根據 a 的每一條記錄去和 DistributeCache 中 b 表對應的 HashTable 關聯,并直接輸出結果,因為沒有 Reduce,所以有多少個 Map Task,就有多少個結果文件。
【注意】Map JOIN 不適合 FULL/RIGHT OUTER JOIN。