0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Join在Spark中是如何組織運行的

人工智能與大數(shù)據(jù)技術(shù) ? 來源:人工智能與大數(shù)據(jù)技術(shù) ? 作者:人工智能與大數(shù)據(jù) ? 2020-09-25 11:35 ? 次閱讀

Join作為SQL中一個重要語法特性,幾乎所有稍微復(fù)雜一點的數(shù)據(jù)分析場景都離不開Join,如今Spark SQL(Dataset/DataFrame)已經(jīng)成為Spark應(yīng)用程序開發(fā)的主流,作為開發(fā)者,我們有必要了解Join在Spark中是如何組織運行的。

SparkSQL總體流程介紹

在闡述Join實現(xiàn)之前,我們首先簡單介紹SparkSQL的總體流程,一般地,我們有兩種方式使用SparkSQL,一種是直接寫sql語句,這個需要有元數(shù)據(jù)庫支持,例如Hive等,另一種是通過Dataset/DataFrame編寫Spark應(yīng)用程序。如下圖所示,sql語句被語法解析(SQL AST)成查詢計劃,或者我們通過Dataset/DataFrame提供的APIs組織成查詢計劃,查詢計劃分為兩大類:邏輯計劃和物理計劃,這個階段通常叫做邏輯計劃,經(jīng)過語法分析(Analyzer)、一系列查詢優(yōu)化(Optimizer)后得到優(yōu)化后的邏輯計劃,最后被映射成物理計劃,轉(zhuǎn)換成RDD執(zhí)行。

對于語法解析、語法分析以及查詢優(yōu)化,本文不做詳細闡述,本文重點介紹Join的物理執(zhí)行過程。

Join基本要素

如下圖所示,Join大致包括三個要素:Join方式、Join條件以及過濾條件。其中過濾條件也可以通過AND語句放在Join條件中。

Spark支持所有類型的Join,包括:

inner join

left outer join

right outer join

full outer join

left semi join

left anti join

下面分別闡述這幾種Join的實現(xiàn)。

Join基本實現(xiàn)流程

總體上來說,Join的基本實現(xiàn)流程如下圖所示,Spark將參與Join的兩張表抽象為流式遍歷表(streamIter)和查找表(buildIter),通常streamIter為大表,buildIter為小表,我們不用擔(dān)心哪個表為streamIter,哪個表為buildIter,這個spark會根據(jù)join語句自動幫我們完成。

在實際計算時,spark會基于streamIter來遍歷,每次取出streamIter中的一條記錄rowA,根據(jù)Join條件計算keyA,然后根據(jù)該keyA去buildIter中查找所有滿足Join條件(keyB==keyA)的記錄rowBs,并將rowBs中每條記錄分別與rowAjoin得到j(luò)oin后的記錄,最后根據(jù)過濾條件得到最終join的記錄。

從上述計算過程中不難發(fā)現(xiàn),對于每條來自streamIter的記錄,都要去buildIter中查找匹配的記錄,所以buildIter一定要是查找性能較優(yōu)的數(shù)據(jù)結(jié)構(gòu)。spark提供了三種join實現(xiàn):sort merge join、broadcast join以及hash join。

sort merge join實現(xiàn)

要讓兩條記錄能join到一起,首先需要將具有相同key的記錄在同一個分區(qū),所以通常來說,需要做一次shuffle,map階段根據(jù)join條件確定每條記錄的key,基于該key做shuffle write,將可能join到一起的記錄分到同一個分區(qū)中,這樣在shuffle read階段就可以將兩個表中具有相同key的記錄拉到同一個分區(qū)處理。前面我們也提到,對于buildIter一定要是查找性能較優(yōu)的數(shù)據(jù)結(jié)構(gòu),通常我們能想到hash表,但是對于一張較大的表來說,不可能將所有記錄全部放到hash表中,另外也可以對buildIter先排序,查找時按順序查找,查找代價也是可以接受的,我們知道,spark shuffle階段天然就支持排序,這個是非常好實現(xiàn)的,下面是sort merge join示意圖。

在shuffle read階段,分別對streamIter和buildIter進行merge sort,在遍歷streamIter時,對于每條記錄,都采用順序查找的方式從buildIter查找對應(yīng)的記錄,由于兩個表都是排序的,每次處理完streamIter的一條記錄后,對于streamIter的下一條記錄,只需從buildIter中上一次查找結(jié)束的位置開始查找,所以說每次在buildIter中查找不必重頭開始,整體上來說,查找性能還是較優(yōu)的。

broadcast join實現(xiàn)

為了能具有相同key的記錄分到同一個分區(qū),我們通常是做shuffle,那么如果buildIter是一個非常小的表,那么其實就沒有必要大動干戈做shuffle了,直接將buildIter廣播到每個計算節(jié)點,然后將buildIter放到hash表中,如下圖所示。

從上圖可以看到,不用做shuffle,可以直接在一個map中完成,通常這種join也稱之為map join。那么問題來了,什么時候會用broadcast join實現(xiàn)呢?這個不用我們擔(dān)心,spark sql自動幫我們完成,當buildIter的估計大小不超過參數(shù)spark.sql.autoBroadcastJoinThreshold設(shè)定的值(默認10M),那么就會自動采用broadcast join,否則采用sort merge join。

hash join實現(xiàn)

除了上面兩種join實現(xiàn)方式外,spark還提供了hash join實現(xiàn)方式,在shuffle read階段不對記錄排序,反正來自兩格表的具有相同key的記錄會在同一個分區(qū),只是在分區(qū)內(nèi)不排序,將來自buildIter的記錄放到hash表中,以便查找,如下圖所示。

不難發(fā)現(xiàn),要將來自buildIter的記錄放到hash表中,那么每個分區(qū)來自buildIter的記錄不能太大,否則就存不下,默認情況下hash join的實現(xiàn)是關(guān)閉狀態(tài),如果要使用hash join,必須滿足以下四個條件:

buildIter總體估計大小超過spark.sql.autoBroadcastJoinThreshold設(shè)定的值,即不滿足broadcast join條件

開啟嘗試使用hash join的開關(guān),spark.sql.join.preferSortMergeJoin=false

每個分區(qū)的平均大小不超過spark.sql.autoBroadcastJoinThreshold設(shè)定的值,即shuffle read階段每個分區(qū)來自buildIter的記錄要能放到內(nèi)存中

streamIter的大小是buildIter三倍以上

所以說,使用hash join的條件其實是很苛刻的,在大多數(shù)實際場景中,即使能使用hash join,但是使用sort merge join也不會比hash join差很多,所以盡量使用hash

下面我們分別闡述不同Join方式的實現(xiàn)流程。

inner join

inner join是一定要找到左右表中滿足join條件的記錄,我們在寫sql語句或者使用DataFrame時,可以不用關(guān)心哪個是左表,哪個是右表,在spark sql查詢優(yōu)化階段,spark會自動將大表設(shè)為左表,即streamIter,將小表設(shè)為右表,即buildIter。這樣對小表的查找相對更優(yōu)。其基本實現(xiàn)流程如下圖所示,在查找階段,如果右表不存在滿足join條件的記錄,則跳過。

left outer join

left outer join是以左表為準,在右表中查找匹配的記錄,如果查找失敗,則返回一個所有字段都為null的記錄。我們在寫sql語句或者使用DataFrmae時,一般讓大表在左邊,小表在右邊。其基本實現(xiàn)流程如下圖所示。

right outer join

right outer join是以右表為準,在左表中查找匹配的記錄,如果查找失敗,則返回一個所有字段都為null的記錄。所以說,右表是streamIter,左表是buildIter,我們在寫sql語句或者使用DataFrame時,一般讓大表在右邊,小表在左邊。其基本實現(xiàn)流程如下圖所示。

full outer join

full outer join相對來說要復(fù)雜一點,總體上來看既要做left outer join,又要做right outer join,但是又不能簡單地先left outer join,再right outer join,最后union得到最終結(jié)果,因為這樣最終結(jié)果中就存在兩份inner join的結(jié)果了。因為既然完成left outer join又要完成right outer join,所以full outer join僅采用sort merge join實現(xiàn),左邊和右表既要作為streamIter,又要作為buildIter,其基本實現(xiàn)流程如下圖所示。

由于左表和右表已經(jīng)排好序,首先分別順序取出左表和右表中的一條記錄,比較key,如果key相等,則joinrowA和rowB,并將rowA和rowB分別更新到左表和右表的下一條記錄;如果keyAkeyB,則說明左表中沒有與右表rowB對應(yīng)的記錄,那么joinnullRow與rowB,緊接著,rowB更新到右表的下一條記錄。如此循環(huán)遍歷直到左表和右表的記錄全部處理完。

left semi join

left semi join是以左表為準,在右表中查找匹配的記錄,如果查找成功,則僅返回左邊的記錄,否則返回null,其基本實現(xiàn)流程如下圖所示。

left anti join

left anti join與left semi join相反,是以左表為準,在右表中查找匹配的記錄,如果查找成功,則返回null,否則僅返回左邊的記錄,其基本實現(xiàn)流程如下圖所示。

總結(jié)

Join是數(shù)據(jù)庫查詢中一個非常重要的語法特性,在數(shù)據(jù)庫領(lǐng)域可以說是“得join者得天下”,SparkSQL作為一種分布式數(shù)據(jù)倉庫系統(tǒng),給我們提供了全面的join支持,并在內(nèi)部實現(xiàn)上無聲無息地做了很多優(yōu)化,了解join的實現(xiàn)將有助于我們更深刻的了解我們的應(yīng)用程序的運行軌跡。

責(zé)任編輯:xj

原文標題:面試必知的 Spark SQL 幾種 Join 實現(xiàn)

文章出處:【微信公眾號:人工智能與大數(shù)據(jù)技術(shù)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • SQL
    SQL
    +關(guān)注

    關(guān)注

    1

    文章

    781

    瀏覽量

    44820
  • SPARK
    +關(guān)注

    關(guān)注

    1

    文章

    106

    瀏覽量

    20420

原文標題:面試必知的 Spark SQL 幾種 Join 實現(xiàn)

文章出處:【微信號:TheBigData1024,微信公眾號:人工智能與大數(shù)據(jù)技術(shù)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 0人收藏

    評論

    相關(guān)推薦
    熱點推薦

    組織塊使用說明

    電子發(fā)燒友網(wǎng)站提供《組織塊使用說明.pdf》資料免費下載
    發(fā)表于 04-02 15:29 ?0次下載

    NVIDIA加速的Apache Spark助力企業(yè)節(jié)省大量成本

    隨著 NVIDIA 推出 Aether 項目,通過采用 NVIDIA 加速的 Apache Spark 企業(yè)得以自動加速其數(shù)據(jù)中心規(guī)模的分析工作負載,從而節(jié)省數(shù)百萬美元。
    的頭像 發(fā)表于 03-25 15:09 ?448次閱讀
    NVIDIA加速的Apache <b class='flag-5'>Spark</b>助力企業(yè)節(jié)省大量成本

    TouchFX Designer運行工程,提示頭文件找不到,為什么?

    TouchFX Designer 運行工程,提示頭文件找不到。 但是keil是可以編譯通過的。 請問如何添加編譯的頭文件到設(shè)計器
    發(fā)表于 03-13 08:20

    OpenVINO?運行應(yīng)用程序失敗怎么解決?

    嘗試 OpenVINO? 運行我的推理應(yīng)用程序失敗,并出現(xiàn)以下錯誤: RuntimeError: Check \'false\' failed at src/core/src/runtime/ov_tensor.cpp:67
    發(fā)表于 03-05 10:29

    Visual Studio運行Hello分類樣本 ,僅在Visual Studio輸出收到錯誤消息,怎么解決?

    Visual Studio* 運行 Hello 分類樣本 ,僅在 Visual Studio* 輸出收到錯誤消息: Exception thrown
    發(fā)表于 03-05 08:16

    車時代電氣列車自主運行系統(tǒng)通過行業(yè)評審

    近日,中國城市軌道交通協(xié)會技術(shù)裝備專業(yè)委員會在寧波組織公司列車自主運行系統(tǒng)(tSafer-UC4000)現(xiàn)場試驗驗證評審會。
    的頭像 發(fā)表于 01-15 13:44 ?644次閱讀

    使用拉曼光譜檢測組織的惡性變化

    介紹 準確、快速、無創(chuàng)地檢測和診斷組織的惡性疾病是生物醫(yī)學(xué)研究的重要目標。漫反射、熒光光譜和拉曼光譜等光學(xué)方法都已被研究作為實現(xiàn)這一目標的方法。漫反射利用組織的吸收和散射特性,特別是細胞核和基質(zhì)
    的頭像 發(fā)表于 10-17 06:32 ?425次閱讀
    使用拉曼光譜檢測<b class='flag-5'>組織</b>的惡性變化

    DVEVM上通過ddd運行Demo

    電子發(fā)燒友網(wǎng)站提供《DVEVM上通過ddd運行Demo.pdf》資料免費下載
    發(fā)表于 10-15 10:05 ?0次下載
    <b class='flag-5'>在</b>DVEVM上通過ddd<b class='flag-5'>運行</b>Demo

    ARM處理器的寄存器組織及功能

    ARM處理器的寄存器組織是其核心架構(gòu)的重要組成部分,對于理解ARM處理器的運行機制和性能特點具有重要意義。以下是對ARM處理器寄存器組織及功能的詳細闡述。
    的頭像 發(fā)表于 09-10 11:11 ?2529次閱讀

    spark為什么比mapreduce快?

    spark為什么比mapreduce快? 首先澄清幾個誤區(qū): 1:兩者都是基于內(nèi)存計算的,任何計算框架都肯定是基于內(nèi)存的,所以網(wǎng)上說的spark是基于內(nèi)存計算所以快,顯然是錯誤的 2;DAG計算模型
    的頭像 發(fā)表于 09-06 09:45 ?476次閱讀

    廣汽能源與泰國Spark EV簽訂合作框架協(xié)議

    近日,廣汽能源科技(泰國)有限公司與Spark EV Co.Ltd.宣布達成重要合作,雙方共同簽署了一項合作框架協(xié)議,旨在泰國境內(nèi)全面布局并運營超級充電場站,為新能源汽車的普及與發(fā)展注入強勁動力。
    的頭像 發(fā)表于 07-19 17:08 ?1080次閱讀

    電容單相電機的作用

    單相電機是一種常見的電機類型,廣泛應(yīng)用于家用電器、工業(yè)設(shè)備和商業(yè)設(shè)施。單相電機的工作原理與三相電機不同,其主要特點是只有一個電源相,因此需要特殊的啟動和運行機制。單相電機,電容的
    的頭像 發(fā)表于 07-19 15:32 ?3588次閱讀

    spark運行的基本流程

    記錄和分享下spark運行的基本流程。 一、spark的基礎(chǔ)組件及其概念 1. ClusterManager Standalone模式
    的頭像 發(fā)表于 07-02 10:31 ?675次閱讀
    <b class='flag-5'>spark</b><b class='flag-5'>運行</b>的基本流程

    Spark基于DPU的Native引擎算子卸載方案

    ?和 R?等多種高級編程語言,這使得Spark可以應(yīng)對各種復(fù)雜的大數(shù)據(jù)應(yīng)用場景,例如金融、電商、社交媒體等。 Spark 經(jīng)過多年發(fā)展,作為基礎(chǔ)的計算框架,不管是
    的頭像 發(fā)表于 06-28 17:12 ?979次閱讀
    <b class='flag-5'>Spark</b>基于DPU的Native引擎算子卸載方案

    關(guān)于Spark的從0實現(xiàn)30s內(nèi)實時監(jiān)控指標計算

    前言 說起Spark,大家就會自然而然地想到Flink,而且會不自覺地將這兩種主流的大數(shù)據(jù)實時處理技術(shù)進行比較。然后最終得出結(jié)論:Flink實時性大于Spark。 的確,F(xiàn)link的數(shù)據(jù)計算
    的頭像 發(fā)表于 06-14 15:52 ?707次閱讀

    電子發(fā)燒友

    中國電子工程師最喜歡的網(wǎng)站

    • 2931785位工程師會員交流學(xué)習(xí)
    • 獲取您個性化的科技前沿技術(shù)信息
    • 參加活動獲取豐厚的禮品