hive on spark 之通过spark web ui详解数据倾斜及思路历程

 然后我看了一下sql

                   FROM ODSERPDATA.FA_ADDITIONS_B                                FA --
                   JOIN ODSERPDATA.FA_BOOKS                                             FB --
                     ON FB.ASSET_ID = FA.ASSET_ID
                   JOIN DWINTDATA.DW_F_FA_DEPRNS_TMP1                       T-- 这个是临时表
                     ON T.ASSET_ID = FA.ASSET_ID
                    AND T.BOOK_TYPE_CODE = FB.BOOK_TYPE_CODE
                   JOIN ODSERPDATA.FA_BOOK_CONTROLS                           FBC
                     ON FBC.BOOK_TYPE_CODE = FB.BOOK_TYPE_CODE
                   JOIN ODSERPDATA.GL_LEDGERS                                          SOB --  
                     ON SOB.LEDGER_ID = FBC.SET_OF_BOOKS_ID
                   JOIN ODSERPDATA.FA_CATEGORY_BOOKS                         FCB ----
                     ON FCB.BOOK_TYPE_CODE = FB.BOOK_TYPE_CODE
                   JOIN ODSERPDATA.FA_ASSET_HISTORY                               FAH ----
                     ON FAH.CATEGORY_ID = FCB.CATEGORY_ID
                    AND FAH.ASSET_ID = FB.ASSET_ID
                   JOIN ODSERPDATA.GL_CODE_COMBINATIONS                     GCC ---
                     ON GCC.CODE_COMBINATION_ID = T.CODE_COMBINATION_ID
                   JOIN ODSERPDATA.FA_LOCATIONS                                          FL-------
                     ON T.LOCATION_ID = FL.LOCATION_ID

差不多就是如下 a join b  join c join d  join e join f 一长串。说实话我也难搞,每次就是一长串sql让我找问题 让我优化,我看完sql理解下都要十几分钟。。。

思路1:任务跑不动可能是数据量太大

首先肯定是数据量太大, 如果abcdefgh十几个表每个表数据量都是几万,那么就算都join在一块,也不会出现跑不动的情况。。

那我们就开始找大表。

select count(1) from DWINTDATA.DW_F_FA_DEPRNS_TMP1   --3492814
select count(1) from ODSERPDATA.FA_ADDITIONS_B          --7353046
select count(1) from ODSERPDATA.FA_BOOKS             --9528477
select count(1) from ODSERPDATA.FA_BOOK_CONTROLS     --558
select count(1) from ODSERPDATA.GL_LEDGERS              --160
select count(1) from ODSERPDATA.FA_CATEGORY_BOOKS    --36035
select count(1) from ODSERPDATA.FA_ASSET_HISTORY     --11585417  --注意这个
select count(1) from ODSERPDATA.GL_CODE_COMBINATIONS --26958010

找到了这么几个大表。其实数据也不算多。

思路二:任务跑不动可能是资源划分太少。

set spark.driver.memory=6G

set spark.executor.cores=4;

set spark.executor.memory=4G;

set spark.executor.instances=10;

加了之后发现task 还是会卡住,但是卡的好像少了一个。。等会附图

思路三:任务跑不动极有可能是数据倾斜(重点!!)

任务一般会分多个stage,一个stage划分多个task,stage可以看做join,task可以看成任务真正运行的。所以我们看到的卡住的task,如下图473tasks结果就一个失败了,极有可能是数据倾斜了,而且按照跑的时间来看 大概率是倾斜的贼多!!!

 那么怎么分辨哪个表数据倾斜呢?

1 机缘巧合之下 发现表的数据倾斜

select count(1) from ODSERPDATA.FA_ASSET_HISTORY     --11585417  --注意这个

然后我看spark web ui 的时候,这里任务已经开始卡住了

点进这个stage细看咦这里怎么刚好有个 shuffle writeMax =11585417

 其实这里不是特别明白这个 shuffle write是哪一步了 ,但是这个stage卡住了,刚好这个数字相等,那么总归有点关系的。

2.最朴素的办法发现数据倾斜。一个个select count(),joinkey group by  joinkey

倾斜的根本原因就是join 偶尔 group 也有。

以上表为例ODSERPDATA.FA_ASSET_HISTORY 

那么我们把这个sql简化为

select 
FB.BOOK_TYPE_CODE ,FB.ASSET_ID,
FCB.BOOK_TYPE_CODE,FCB.CATEGORY_ID,
FAH.CATEGORY_ID,FAH.ASSET_ID,
from ODSERPDATA.FA_BOOKS                      FB ----7353046
JOIN ODSERPDATA.FA_CATEGORY_BOOKS            FCB --9528477
ON FCB.BOOK_TYPE_CODE = FB.BOOK_TYPE_CODE
JOIN ODSERPDATA.FA_ASSET_HISTORY             FAH --11585417
on  FAH.ASSET_ID = FB.ASSET_ID
AND FAH.CATEGORY_ID = FCB.CATEGORY_ID

然后查出他们的joinkey的分布情况。 

ODSERPDATA.FA_BOOKS                      FB.BOOK_TYPE_CODE和 FB.ASSET_ID

注意这两个key是分别关联的。 所以不要用group by FB.BOOK_TYPE_CODE,FB.ASSET_ID

上面这个一看就很均匀 

book_type_code=105_FA_BOOK==7178652=700w就一个  --注意这条数据

然后10w-20w的有7个,1-10w的有20个。

 上面这个一看,好家伙,这个很明显就是数据倾斜了。 但是也不要确定,因为万一700w的这个数据就是摆设呢?谁也关联不到。

ODSERPDATA.FA_CATEGORY_BOOKS joinkey BOOK_TYPE_CODE  CATEGORY_ID

 CATEGORY_ID 平平无奇 都是200 199 198

 BOOK_TYPE_CODE 也是平平无奇,但是注意我上面提到的那条700w的数据

上面的book_type_code=105_FA_BOOK=700w

这里的book_type_code=105_FA_BOOK=401

两者join 在不过滤其他的条件的情况下 401*700w=28亿条数据。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

所以问题出在哪里?答案就是

select 
FB.BOOK_TYPE_CODE ,FB.ASSET_ID,
FCB.BOOK_TYPE_CODE,FCB.CATEGORY_ID
from ODSERPDATA.FA_BOOKS                      FB ----7353046
JOIN ODSERPDATA.FA_CATEGORY_BOOKS            FCB --9528477
ON FCB.BOOK_TYPE_CODE = FB.BOOK_TYPE_CODE

就是这个继续简化的sql了。

我们单独执行这个sql 看下

45s 473个task 已经完成了470个 有3个卡住了。 

 继续点进去看下 注意右下角有个7179053 我们之前的那个key是105_FA_BOOK= 7178652 看着有点像又有点多了

7179053-7178652=101 这多的401有没有小伙伴知道哪来的?

因为105_FA_BOOK 有7178652 ,其余的key有的十万 有的1w 有的100 有的10 有的1 

如下图 这个字段的key共有263个,其中core因为设置了动态调整,不知道的可以百度spark.dynamicAllocation.enabled=true ,举个例子就是

105_FA_BOOK +10X_FA_BOOK++10X_FA_BOOK++10X_FA_BOOK=7179053

 解释完了 我们再好好的看下任务

跑了10分钟 3个顽固分子也倒下了2个 还剩我说的700w那个。我们看看其他的是不是和我说的一一样 

13.5 GB / 2720441164.4 MB / 726822

 这个 726822 应该是这个69w+其他的几个key了。大概算下

692584*387=268030008 和上述的272044116也差不多。注意这个输出了13.5G,那我们先前算的28亿差不多就是135G。。。所以啊,为啥任务跑不动,为啥/tmp的磁盘容易被打爆,原因出来了吧。。

话也说到这里了。那么重头戏来了,怎么解决。其实这种方法大家说了很多了,无非就是小表扩容大表打散。

select FB.BOOK_TYPE_CODE,
       FB.ASSET_ID,
       FB.book_type_code_random,
       FCB.BOOK_TYPE_CODE,
       FCB.CATEGORY_ID,
       FCB.book_type_code_random
from (
         select FB.BOOK_TYPE_CODE,
                FB.ASSET_ID,
                case book_type_code
                    when '105_FA_BOOK' then concat(book_type_code, "_", floor(RAND() * 10)) --大表随机1-9
                    else book_type_code
                    end as book_type_code_random
         from ODSERPDATA.FA_BOOKS FB) FB ----7353046
         JOIN (
    select concat(book_type_code, random) book_type_code_random, BOOK_TYPE_CODE, CATEGORY_ID
    from (
             select case book_type_code
                        when '105_FA_BOOK' then concat_ws('_', '1', '2', '3', '4', '5', '6', '7', '8', '9')
                        else ""
                        end as repeat_number,
                    BOOK_TYPE_CODE,
                    CATEGORY_ID
             from ODSERPDATA.FA_CATEGORY_BOOKS -- 小表扩容1-9 增加了八倍
         ) t lateral view explode(split(repeat_number, "_")) table_tmp as random
) FCB
              ON FCB.book_type_code_random = FB.book_type_code_random

花费时间4min 可以接受

 看右边都是70w-80w 就是我们700w数据打散后的数据

多说两句这个的核心思想其实就是

700w*400=28亿变成了

400*10扩容十倍   700w打散十份

400*70w+400*80w+400*60w+400*70w+400*70w+400*70w....=400*(700w)=28亿

重要的是小表等额扩容。 不要扩容成 400 398 402这种了。

大表随机打散打的不是太散不会影响结果的。

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值