然后我看了一下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 的时候,这里任务已经开始卡住了
其实这里不是特别明白这个 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+ 10 X _FA_BOOK++ 10 X _FA_BOOK++ 10 X _FA_BOOK=7179053
解释完了 我们再好好的看下任务
跑了10分钟 3个顽固分子也倒下了2个 还剩我说的700w那个。我们看看其他的是不是和我说的一一样
13.5 GB / 272044116 4.4 MB / 726822
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打散十份
40070w+40080w+40060w+40070w+40070w+40070w….=400*(700w)=28亿
重要的是小表等额扩容。 不要扩容成 400 398 402这种了。
大表随机打散打的不是太散不会影响结果的。
Original: https://blog.csdn.net/cclovezbf/article/details/127419794
Author: cclovezbf
Title: hive on spark 之通过spark web ui详解数据倾斜及思路历程
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/817752/
转载文章受原作者版权保护。转载请注明原作者出处!