<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          奇思妙想的SQL|兼顧性能的數(shù)據(jù)傾斜處理新姿勢

          共 16558字,需瀏覽 34分鐘

           ·

          2024-04-11 21:37


          阿里妹導(dǎo)讀


          本篇為系列第2篇,分享在支付寶支付數(shù)據(jù)鏈路改造升級過程中,針對數(shù)據(jù)傾斜的優(yōu)化實踐新方法,在解決數(shù)據(jù)傾斜問題的同時,還能兼顧更優(yōu)的計算性能!

          文章導(dǎo)讀

          SQL作為目前最通用的數(shù)據(jù)庫查詢語言,其功能和特性復(fù)雜度遠不止大家常用的“SELECT * FROM tbl”這樣簡單,一段好的SQL和差的SQL,其性能可能有幾十乃至上千倍的差距。而寫出一個好的能兼顧性能和易用性的SQL,考驗的不僅僅是了解到多少新特性新寫法,而是要深入理解數(shù)據(jù)的處理過程,然后設(shè)計好數(shù)據(jù)的處理過程。
          因此想推出本系列文章,并取名為《奇思妙想的SQL》,希望能以實際案例出發(fā),和大家分享一些SQL處理數(shù)據(jù)的新方案新思路,并在過程中融入對問題本質(zhì)的理解,希望大家能喜歡~
          本篇為系列第2篇,分享下在支付寶支付數(shù)據(jù)鏈路改造升級過程中,針對數(shù)據(jù)傾斜的優(yōu)化實踐新方法,在解決數(shù)據(jù)傾斜問題的同時,還能兼顧更優(yōu)的計算性能!

          一、場景描述

          數(shù)據(jù)傾斜的處理,作為校招/社招最經(jīng)典的一道面試題,相信作為一名數(shù)據(jù)研發(fā)同學(xué),多少都有些了解。數(shù)據(jù)傾斜可能發(fā)生在join、group by、Count Distinct等環(huán)節(jié),但本質(zhì)上其實都類似,即因為數(shù)據(jù)重分發(fā)或重分布等原因,導(dǎo)致大部分數(shù)據(jù)分發(fā)至少數(shù)幾個計算節(jié)點上,閑著大伙兒,累死少數(shù)幾個兄弟。問題表象也好識別,以O(shè)DPS場景為例,少數(shù)幾個Fuxi Instance處理的數(shù)據(jù)量,遠大于同一環(huán)節(jié)的其他Instance處理的數(shù)據(jù)量,并伴有明顯的長尾現(xiàn)象。
          典型的案例就是淘寶雙十一場景中,交易訂單明細大表需要關(guān)聯(lián)商家信息維表以補全商家信息,在數(shù)據(jù)關(guān)聯(lián)處理中,同一個商家對應(yīng)的交易訂單和維表對應(yīng)商家信息,將根據(jù)賣家ID shuffle至同一個數(shù)據(jù)處理節(jié)點上。由于TOP商家在大促中產(chǎn)生的交易單量遠大于普通商家,從而導(dǎo)致大量的數(shù)據(jù)集中到一臺或者幾臺機器上計算,這些數(shù)據(jù)的計算速度將遠遠低于平均計算速度,導(dǎo)致整個計算過程被拖慢。


          如上圖所示,數(shù)據(jù)重分發(fā)過程中,按照Join Key(即賣家ID)進行Shuffle,大部分交易數(shù)據(jù)記錄分發(fā)至處理節(jié)點1,導(dǎo)致三個并發(fā)處理節(jié)點中,處理節(jié)點1需要處理的數(shù)據(jù)量遠大于其他兩個處理節(jié)點,從而造成數(shù)據(jù)處理的不均勻,即數(shù)據(jù)傾斜。

          二、常見的優(yōu)化方法

          2.1.Mapjoin

          Mapjoin的好處自不必多言,通過把小表廣播到大表所在計算節(jié)點上,有效避免了大表的Shuffle,自然也就避免了數(shù)據(jù)重分布導(dǎo)致的數(shù)據(jù)傾斜。若大表數(shù)據(jù)的原始分布本身就有不均勻的情況,此時也可以通過增加隨機重分布的臨時打散方式,將數(shù)據(jù)打得散一些,再通過Mapjoin實現(xiàn)數(shù)據(jù)關(guān)聯(lián)。
          SELECT /*+MAPJOIN(dim)*/  * FROM (SELECT * FROM dwd_tbl) base LEFT OUTER JOIN (SELECT * FROM dim_tbl) dimON base.dim_key = dim.dim_key

          2.2.特殊值/空值打散

          • 特殊值/空值場景也比較普遍,比如主表中有個屬性字段在某些場景下為空或為一些無業(yè)務(wù)含義的特殊字符串(如DEFAULT),然后此屬性字段本身對應(yīng)了一張數(shù)據(jù)量較大的維表,需要關(guān)聯(lián)打?qū)捬a全。此時做數(shù)據(jù)關(guān)聯(lián),由于兩張表需要按照關(guān)聯(lián)key進行shuffle,就會導(dǎo)致主表中該字段為空/相同特殊字符串的數(shù)據(jù)記錄shuffle到同一節(jié)點上,從而導(dǎo)致數(shù)據(jù)傾斜。
          • 此類場景也好解決,對特殊值/空值在關(guān)聯(lián)時轉(zhuǎn)為隨機值就行。
          SELECT * FROM (SELECT * FROM dwd_tbl) base LEFT OUTER JOIN (SELECT * FROM dim_tbl) dimON IF(COALESCE(base.dim_key,'')='',CONCAT('HIVE_',RAND()),base.dim_key) = dim.dim_key

          2.3.熱點值打散,副表呈倍數(shù)擴散

          • 此類方法使用較少,核心在于對于主表附加一個隨機值(比如1~10)字段,記為ext_a字段,然后對應(yīng)被關(guān)聯(lián)維表數(shù)據(jù)按照對應(yīng)倍數(shù)進行復(fù)制膨脹,并依次賦予1~10的編號,記為ext_b字段,然后在關(guān)聯(lián)兩張表時把ext_a、ext_b兩個字段也作為關(guān)聯(lián)字段之一。
          • 此方法適用于被關(guān)聯(lián)表遠比主表小,但又因數(shù)據(jù)大小超過內(nèi)存容量而無法使用Mapjoin,且主表的數(shù)據(jù)傾斜程度不大(即極值對應(yīng)的數(shù)據(jù)行數(shù)相較于值平均對應(yīng)行數(shù),倍數(shù)差距不太大)的情況下可以使用,但整體上此方案只能對數(shù)據(jù)熱點成倍數(shù)的削弱一些。
          SELECT * FROM (    SELECT *,CAST(RAND()*10 AS BIGINT) AS ext_a    FROM dwd_tbl) base LEFT OUTER JOIN (    SELECT *    FROM dim_tbl    LATERAL VIEW EXPLODE(SPLIT('0;1;2;3;4;5;6;7;8;9',';')) tt AS ext_b    -- 或者Join一個用于倍數(shù)膨脹的小表) dimON  base.dim_key = dim.dim_keyAND base.ext_a   = dim.ext_b


          2.4.熱點數(shù)據(jù)單獨處理/SkewJoin

          • 使用此方法通常也意味著被關(guān)聯(lián)的維表數(shù)據(jù)大小較大,無法使用Mapjoin,只能走普通shuffle模式的join方案。此類場景最典型的案例就是雙十一淘系交易大表關(guān)聯(lián)商家維表,此時的商家維表因記錄數(shù)和數(shù)據(jù)大小都較大而無法放入內(nèi)存,再加上部分商家的交易單量遠超大盤平均,此時的數(shù)據(jù)傾斜就得使用熱點數(shù)據(jù)單獨處理的方案了。

          • 熱點數(shù)據(jù)單獨處理的方案的核心點在于將熱點數(shù)據(jù)提取出來單獨處理,熱點數(shù)據(jù)可以用Mapjoin的方式完成關(guān)聯(lián)維表熱點記錄行,非熱點則使用普通的shuffle模式的join方案完成關(guān)聯(lián)。

          • 具體操作主要分三個部分:基于主表統(tǒng)計獲得Top熱點的屬性值;用熱點屬性值將被關(guān)聯(lián)維表拆成熱點小表和非熱點表,同時也將主表拆成熱點主表和非熱點主表;熱點小表通過Mapjoin與熱點主表join,非熱點表與非熱點主表join,最終兩部分再Union到一起,完成數(shù)據(jù)關(guān)聯(lián)。
          -- Step01:熱點數(shù)據(jù)記錄提取INSERT OVERWRITE TABLE tmp_hot_list PARTITION (dt = '${bizdate}')SELECT   dim_shop_id AS hot_idFROM   main_tableWHERE   dt = '${bizdate}'GROUP BY dim_shop_idHAVING COUNT(1) > 10000;
          INSERT OVERWRITE TABLE final_result_table PARTITION (dt = '${bizdate}')-- Step02:熱點數(shù)據(jù)處理,使用MapJoin完成處理SELECT /*+MAPJOIN(a2,a3)*/ a1.trade_no AS trade_no ,a1.dim_shop_id AS shop_id ,a3.shop_name AS shop_name ,a3.shop_type AS shop_typeFROM (SELECT * FROM main_table WHERE dt = '${bizdate}') a1 -- Step02-1:主表用JOIN關(guān)聯(lián)熱點表進行熱點記錄篩選JOIN (SELECT * FROM tmp_hot_list WHERE dt = '${bizdate}') a2 -- 熱點數(shù)據(jù)清單ON a1.dim_shop_id = a2.dim_shop_id-- Step02-2:熱點維度數(shù)據(jù)處理LEFT OUTER JOIN ( SELECT /*+MAPJOIN(b2)*/ b1.* FROM (SELECT * FROM dim_table_info WHERE dt = '${bizdate}') b1 JOIN (SELECT * FROM tmp_hot_list WHERE dt = '${bizdate}') b2 -- 熱點數(shù)據(jù)清單 ON b1.dim_shop_id = b2.dim_shop_id) a3ON a1.dim_shop_id = a3.dim_shop_idUNION ALL -- Step03:非熱點數(shù)據(jù)處理,使用普通Join完成處理,兩張表均需要進行ShuffleSELECT /*+MAPJOIN(a12)*/ a11.trade_no AS trade_no ,a11.dim_shop_id AS shop_id ,a13.shop_name AS shop_name ,a13.shop_type AS shop_typeFROM (SELECT * FROM main_table WHERE dt = '${bizdate}') a11 -- Step03-1:主表用ANTI JOIN關(guān)聯(lián)熱點表進行剔除LEFT ANTI JOIN (SELECT * FROM tmp_hot_list WHERE dt = '${bizdate}') a12ON a11.dim_shop_id = a12.dim_shop_id-- Step03-2:非熱點維度數(shù)據(jù)處理LEFT OUTER JOIN ( SELECT /*+MAPJOIN(b12)*/ b11.* FROM (SELECT * FROM dim_table_info WHERE dt = '${bizdate}') b11 LEFT ANTI JOIN (SELECT * FROM tmp_hot_list WHERE dt = '${bizdate}') b12 ON b11.dim_shop_id = b12.dim_shop_id) a13ON a11.dim_shop_id = a13.dim_shop_id;
          • 整個步驟稍有些復(fù)雜,這里也可以直接用平臺的skewjoin參數(shù)完成傾斜處理,skew的核心思路就是上面提到的熱點數(shù)據(jù)單獨處理,只是做了平臺級別的集成,方便用戶一鍵解決數(shù)據(jù)傾斜問題。詳細用法和詳細原理可參考 《阿里云-SKEWJOIN HINT》[1] 。
          INSERT OVERWRITE TABLE final_result_table PARTITION (dt = '${bizdate}')SELECT  /*+SKEWJOIN(a1)*/          a1.trade_no    AS trade_no        ,a1.dim_shop_id AS shop_id        ,a2.shop_name   AS shop_name        ,a2.shop_type   AS shop_typeFROM (SELECT * FROM main_table     WHERE dt = '${bizdate}') a1 LEFT JOIN (SELECT * FROM dim_table_info WHERE dt = '${bizdate}') a2 ON    a1.dim_shop_id = a2.dim_shop_id;

          2.5.方案總結(jié)

          • 不難發(fā)現(xiàn),上面幾種方案核心都是在圍繞解決數(shù)據(jù)重分發(fā)(即shuffle)導(dǎo)致的熱點問題,一種是想方設(shè)法采用Mapjoin的方式避免熱點數(shù)據(jù)重分發(fā),一種是讓數(shù)據(jù)重分發(fā)過程中盡可能得均勻。
          • 不管是哪種思路,問題核心都還是在解決shuffle導(dǎo)致的數(shù)據(jù)分布不均勻的問題。所以,一切的“罪魁禍首”就是 shuffle 、 shuffle shuffle

          三、一種新的思路 WithDistmapjoin~

          3.1.核心思路

          數(shù)據(jù)傾斜的核心在于數(shù)據(jù)處理不均勻,而數(shù)據(jù)處理的不均勻往往又來自數(shù)據(jù)重分發(fā),也就是shuffle。因此如果能解決好shuffle不均勻問題,或者在不需要對大表進行shuffle的同時就能完成數(shù)據(jù)關(guān)聯(lián)計算的操作,就能避免數(shù)據(jù)傾斜問題。在此我們聯(lián)想到了Distmapjoin的能力,通過對中小規(guī)模的表(為便于理解,后文用維表進行替代)構(gòu)建遠程分布式查詢節(jié)點,大表再通過網(wǎng)絡(luò)遠程查詢相關(guān)維表數(shù)據(jù),從而實現(xiàn)了類似于Mapjoin的方式,大表無須shuffle即能完成Join操作。
          在此,預(yù)估Distmapjoin可以非常好的解決大表shuffle導(dǎo)致的數(shù)據(jù)傾斜問題。但我們忽略了一個問題,熱點問題其實還沒消失,只是轉(zhuǎn)移成了遠程網(wǎng)絡(luò)查詢的IO熱點問題。當然在技術(shù)實現(xiàn)細節(jié)上可以通過同一key的多次查詢合并為一次等方案進一步削弱熱點問題,但熱點問題并沒有完全消除。在此,我們可以返回去參考skewjoin的方案,將維表的熱點記錄和非熱點記錄分而治之,只不過此時我們使用的不是“熱點Mapjoin+非熱點shuffle”的方案,而是采用“熱點Mapjoin+非熱點Distmapjoin”的方案。Distmapjoin的方案及原理詳見 《阿里云-DISTRIBUTED MAPJOIN》[2]
          Mapjoin用于處理熱點數(shù)據(jù),將維表熱點記錄廣播至大表所在計算節(jié)點;Distmapjoin用于處理非熱點數(shù)據(jù),用于通過構(gòu)建遠程分布式查詢節(jié)點,實現(xiàn)大表在無需移動的情況下完成數(shù)據(jù)關(guān)聯(lián)操作。 當前方案還額外實現(xiàn)了提效的收益,大表在全流程中均無需shuffle,躺著不動就能實現(xiàn)join操作~

          3.2.代碼實現(xiàn)

          WITH -- STEP01:熱點Key采集tmp_hot_pid AS (    SELECT dim_shop_id,'Y' AS is_hot    FROM main_table_detail    WHERE dt = '${bizdate}'    GROUP BY dim_shop_id    HAVING COUNT(1) > 100000)-- STEP02:維表熱點數(shù)據(jù)打標,tmp_dim_tbl AS (    SELECT   /*+MAPJOIN(hot)*/               dim.*            ,COALESCE(hot.is_hot,'N') AS is_hot    FROM (        SELECT *        FROM dim_table_info        WHERE dt = '${bizdate}'    ) dim    LEFT OUTER JOIN tmp_hot_pid hot     ON dim.dim_shop_id = hot.dim_shop_id)-- STEP03:明細熱點數(shù)據(jù)打標,tmp_dwd_tbl AS (    SELECT /*+MAPJOIN(hot)*/              base.*            ,COALESCE(hot.is_hot,'N') AS is_hot    FROM (        SELECT *        FROM main_table_detail        WHERE dt = '${bizdate}'    ) base     LEFT OUTER JOIN tmp_hot_pid hot     ON base.dim_shop_id = hot.dim_shop_id)
          -- STEP04:數(shù)據(jù)合并處理,熱點數(shù)據(jù)用Mapjoin,非熱點數(shù)據(jù)用DISTMAPJOININSERT OVERWRITE TABLE final_result_table PARTITION (dt = '${bizdate}')SELECT *FROM ( -- STEP04-1:非熱點數(shù)據(jù)用DISTMAPJOIN SELECT /*+ DISTMAPJOIN(dim(shard_count=77)) */ dwd_tbl.trade_no AS trade_no ,dwd_tbl.trade_date AS trade_date ,dwd_tbl.shop_id AS shop_id ,dim.shop_name AS shop_name ,dim.shop_type AS shop_type FROM (SELECT * FROM tmp_dwd_tbl WHERE is_hot = 'N') dwd_tbl LEFT OUTER JOIN (SELECT * FROM tmp_dim_tbl WHERE is_hot = 'N') dim ON dwd_tbl.partner_id = dim.partner_id UNION ALL -- STEP04-1:熱點數(shù)據(jù)用Mapjoin SELECT /*+MAPJOIN(dim)*/ dwd_tbl.trade_no AS trade_no ,dwd_tbl.trade_date AS trade_date ,dwd_tbl.shop_id AS shop_id ,dim.shop_name AS shop_name ,dim.shop_type AS shop_type FROM (SELECT *FROM tmp_dwd_tbl WHERE is_hot = 'Y') dwd_tbl LEFT OUTER JOIN (SELECT *FROM tmp_dim_tbl WHERE is_hot = 'Y') dim ON dwd_tbl.partner_id = dim.partner_id) base ;

          3.3.真實效果

          當前新方案在支付寶核心支付數(shù)據(jù)鏈路上線,給相關(guān)可優(yōu)化節(jié)點帶來了 平均40% 的計算耗時縮減和 平均30% 的計算資源縮減。 方案主要應(yīng)用于支付交易join商家維表、支付交易join合約維表等場景,方案將原本需要手動拆分熱點利用“Mapjoin+shuffle進行熱點數(shù)據(jù)處理”的過程,改為利用Distmapjoin或Mapjoin+Distmapjoin的方案,讓支付交易大表在計算全過程中均無需移動,在解決數(shù)據(jù)傾斜問題的同時,也實現(xiàn)了降低計算資源和提升產(chǎn)出時效。
          另外值得說的一點,我們對域內(nèi)的支付交易數(shù)據(jù)鏈路進行了全鏈路HashCluster的處理,結(jié)合Distmapjoin的傾斜處理方案,可有效避免已經(jīng)排好序的HC表再二次重分桶,全鏈路加工過程中都可以保持其原本已經(jīng)設(shè)定好的HashCluster分桶策略~

          四、方案總結(jié)

          上面介紹了一種結(jié)合Mapjoin和Distmapjoin的數(shù)據(jù)傾斜處理方案,在有效解決數(shù)據(jù)傾斜問題的同時還可以避免大表的shuffle,提供了更優(yōu)的性能表現(xiàn)。實際上如果數(shù)據(jù)傾斜情況不是特別嚴重(比如 熱點數(shù)據(jù)行/平均單節(jié)點處理數(shù)據(jù)行 < 100),完全可以直接使用純Distmapjoin的方案。
          綜合我們基于Distmapjoin提出的兩種方案,我們結(jié)合各種方案的優(yōu)劣勢進行方案分級,然后根據(jù)具體場景進行更優(yōu)的方案選擇。

          參考鏈接:

          [1]https://help.aliyun.com/zh/maxcompute/user-guide/skewjoin-hint-1?spm=5176.28426678.J_HeJR_wZokYt378dwP-lLl.1.3a415181D3BDr0&scm=20140722.S_help@@文檔@@455433.S_BB2@bl+RQW@ag0+BB1@ag0+os0.ID_455433-RL_ODPS%20SKEWJOIN-LOC_search~UND~helpdoc~UND~item-OR_ser-V_3-P0_0

          [2]https://help.aliyun.com/zh/maxcompute/user-guide/distributed-mapjoin?spm=a2c4g.11186623.0.i1#concept-2197457

          ?

          ?

          瀏覽 37
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  人人操综合 | 骚逼视频免费观看 | 秋霞国产午夜精品免费视频 | 翔田千里无修正XXX | 色色射|