大數據-數據傾斜那些事情

    在平時處理大數據量的過程中,會遇到很多數據傾斜的問題,在業務中很多坑也都踩過了,特此記錄一下。

   首先,有很多的數據傾斜是是在業務場景中發生的。

   其次就是sql或者代碼的問題了。

        以訂單數據爲例,在之前的例行任務中都是正常運行,但是在某一天搞了一個活動,導致某一個商品的訂單數據增加了100倍,然後進行一些group等的操作,這種在處理數據的時候會產生數據傾斜,因爲同一個key(商品id)都shuffle到同一個節點上進行運算,其他節點都運算完成,但是這個節點因爲數據多的問題,一直在執行,所以會產生數據傾斜。

     解決方案:

      1、調研一下數據的情況,如果數據驟增特別大,導致reduce階段一直卡在99%或者各種container報錯OOM,任務跑不出來,那麼這個需要在業務上特殊處理。(如果reduce階段99%的情況持續時間能接受,其實就不需要特殊處理了,只不過產出時間比較晚而已,可以調整一些參數就行了)

      處理的方法也其實有很多的:

    (1)類似於count(distinct ***)的情況改一下寫法,先group by ,再在外層來一次group by聚合。因爲count(distinct ***)之後的數據reduce會卡住,同一個數據都在reduce處理,比較慢。兩層group by 會有預聚合,數據量表少很多,處理起來更快。

    (2)真實數據就是傾斜很嚴重。這樣的話可以單獨先把傾斜的key單獨拿出來計算,和其他key再聚合處理。

具體操作:

    訂單表(abc.order_detail),要求單個商品的成交量、成交額

      先用sql過濾出來key傾斜的情況:(支付訂單的數據表)

WITH big_tmp AS (

select
    item_id,
    count(1) as cnt
from
    abc.order_detail
where
    p_date = '2020-05-01'
group by
    item_id
HAVING
    cnt > 1
)

這個過濾出來的 big_tmp 數據集就是數據量比較大的集合。

   然後在關聯的過程中吧 big_tmp 的數據單獨計算。

WITH big_tmp AS (

select
    item_id,
    count(1) as cnt
from
    abc.order_detail
where
    p_date = '2020-05-01'
group by
    item_id
HAVING
    cnt > 1
) --所有的大數據量的數據 計算
SELECT
    item_id,
    count(1) AS cnt,
    sum(order_detail.spaend) AS total_spend
FROM
    abc.order_detail
    JOIN big_tmp ON order_detail.item_id = big_tmp.item_id
GROUP BY
    item_id
UNION ALL
    --其他數據量較小的數據 計算
SELECT
    count(1) AS cnt,
    sum(order_detail.spaend) AS total_spend
FROM
    (
        SELECT
            item_id,
            spaend
        FROM
            abc.order_detail
            LEFT JOIN big_tmp ON order_detail.item_id = big_tmp.item_id
        WHERE
            big_tmp.item_id IS NULL -- 過濾掉大數據量的 item_id
    ) small
GROUP BY
    item_id

   這樣的話就可以把數據量比較大的 item_id 單獨進行計算了。傾斜的情況就會顯著緩解。

   如果還有問題,可以把item_id打散,進行hash,最後再把數據聚合起來,這樣效率更高。(單獨再出一份博客吧)

https://blog.csdn.net/iilegend/article/details/97682621

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章