HIVE优化场景七--数据倾斜--Join 倾斜

2) 由于数据类型不一致,导致的转换问题,导致的数据倾斜

场景说明:用户表中 user_id 字段为 int,log 表中 user_id 为既有 string 也有 int 的类型。

   当按照两个表的 user_id 进行 join 操作的时候,默认的 hash 操作会按照 int 类型的 id 进 行分配,这样就会导致所有的 string 类型的 id 就被分到同一个 reducer 当中。

解决方案:将 INT 类型id , 转换为 STRING 类型的 id.

SELECT *

FROM user AS a

LEFT OUTER JOIN log AS b

ON b.user_id = CAST (a.user_id AS STRING)

;

3) 业务数据本身分布不均,导致的数据倾斜

i.大表与小表JOIN (Map JOIN)

ii.大表与大表JOIN, 一张表数据分布均匀,另一张表数据特定的KEY(有限几个) 分布不均

iii.大表与大表JOIN, 一张表数据分布均匀,另一张表大量的KEY 分布不均

iiii.大表与大表JOIN, 桶表,进行表拆分

构建数据

CREATE TABLE IF NOT EXISTS skew_multi_action_info(

user_id BIGINT

,user_action STRING

);

INSERT INTO TABLE skew_multi_action_info

VALUES

(1, 'cc')

,(1, 'pp')

,(1, 'kk')

,(1, 'kk')

,(1, 'kk')

,(1, 'kk')

,(1, 'kk')

,(1, 'cc')

,(2, 'zz')

,(2, 'zz')

,(2, 'zz')

,(2, 'zS')

,(2, 'zS')

,(2, 'zS')

,(3, 'pp')

,(4, 'lp')

,(5, 'op')

;

CREATE TABLE IF NOT EXISTS skew_user_info_2(

user_id BIGINT

,user_name STRING

);

INSERT INTO TABLE skew_user_info_2

VALUES

(1, 'puzheli')

,(2, 'sjz')

,(3, 'xxx')

,(4, 'ccc')

,(5, 'xdi')

;

i.大表与小表JOIN (Map JOIN)

我们参考Map JOIN 的参数,去调整 MAP JOIN 的小表的输入大小即可。

参考文章 :https://blog.csdn.net/u010003835/article/details/105495067

Map JOIN 会将小表分发到JOB 中每个 Map 中, 相当于 map 端执行了 JOIN 操作,省去了 shuffle 流程,所以避免了大量相同 KEY 传入到 一个 Reduce 中。

使用Map JOIN 时,会先执行一个本地任务(mapreduce local task)将小表转成hashtable并序列化为文件再压缩,随后这些 hashtable文件会被上传到hadoop缓存,提供给各个mapjoin 使用。


针对上面的 数据,我们设置 hive Map JOIN 默认优化    

set hive.auto.convert.join = true;

我们看下执行计划

STAGE DEPENDENCIES:                               

  Stage-4 is a root stage                         

  Stage-3 depends on stages: Stage-4             

  Stage-0 depends on stages: Stage-3             


STAGE PLANS:                                     

  Stage: Stage-4                                 

    Map Reduce Local Work                         

      Alias -> Map Local Tables:                 

        b                                         

          Fetch Operator                         

            limit: -1                             

      Alias -> Map Local Operator Tree:           

        b                                         

          TableScan                               

            alias: b                             

            Statistics: Num rows: 5 Data size: 29 Basic stats: COMPLETE Column stats: NONE

            HashTable Sink Operator               

              keys:                               

                0 user_id (type: bigint)         

                1 user_id (type: bigint)         


  Stage: Stage-3                                 

    Map Reduce                                   

      Map Operator Tree:                         

          TableScan                               

            alias: a                             

            Statistics: Num rows: 17 Data size: 68 Basic stats: COMPLETE Column stats: NONE

            Map Join Operator                     

              condition map:                     

                    Left Outer Join0 to 1         

              keys:                               

                0 user_id (type: bigint)         

                1 user_id (type: bigint)         

              outputColumnNames: _col0, _col1, _col6

              Statistics: Num rows: 18 Data size: 74 Basic stats: COMPLETE Column stats: NONE

              Select Operator                     

                expressions: _col0 (type: bigint), _col1 (type: string), _col6 (type: string)

                outputColumnNames: _col0, _col1, _col2

                Statistics: Num rows: 18 Data size: 74 Basic stats: COMPLETE Column stats: NONE

                File Output Operator             

                  compressed: false               

                  Statistics: Num rows: 18 Data size: 74 Basic stats: COMPLETE Column stats: NONE

                  table:                         

                      input format: org.apache.hadoop.mapred.SequenceFileInputFormat

                      output format: org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat

                      serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe

      Local Work:                                 

        Map Reduce Local Work                     


  Stage: Stage-0                                 

    Fetch Operator                               

      limit: -1                                   

      Processor Tree:                             

        ListSink                                 

ii.大表与大表JOIN, 一张表数据分布均匀,另一张表数据特定的KEY(有限几个) 分布不均

适用场景:两个Hive表进行join的时候,如果数据量都比较大,那么此时可以看一下两个Hive表中的key分布情况。如果出现数据倾斜,是因为其中某一个Hive表中的少数几个key的数据量过大,而另一个Hive表中的所有key都分布比较均匀,那么采用这个解决方案是比较合适的

方案实现思路:

对包含少数几个数据量过大的key的那个表,通过sample算子采样出一份样本来,然后统计一下每个key的数量,计算出来数据量最大的是哪几个key。

然后将这几个key对应的数据从原来的表中拆分出来,形成一个单独的表,并给每个key都打上n以内的随机数作为前缀,而不会导致倾斜的大部分key形成另外一个表

接着将需要join的另一个表,也过滤出来那几个倾斜key对应的数据并形成一个单独的表,将每条数据膨胀成n条数据,这n条数据都按顺序附加一个0~n的前缀,不会导致倾斜的大部分key也形成另外一个表。

再将附加了随机前缀的独立表与另一个膨胀n倍的独立表进行join,此时就可以将原先相同的key打散成n份,分散到多个task中去进行join了。

而另外两个普通的表就照常join即可。

最后将两次join的结果使用union算子合并起来即可,就是最终的join结果。

数据倾斜的SQL

SELECT

a.*

,b.user_name

FROM skew_multi_action_info AS a

JOIN skew_user_info_2 AS b

ON a.user_id = b.user_id

;


针对上述数据样例:

可以看到  skew_multi_action_info  user_id  IN (1,2) 大量倾斜,skew_user_info_2 表的数据分布 均匀。

所以,我们采用上述方案,拆分并合并的方式

倾斜数据 1,2 的结果

SELECT

tmp_a.uid

,tmp_a.user_action

,tmp_b.user_name

FROM

(

SELECT

CONCAT(a.user_id, '_', CAST ((RAND()*2%2 + 1) AS INT)) AS uid

,a.user_action

FROM skew_multi_action_info AS a

WHERE a.user_id IN (1,2)

) AS tmp_a

JOIN

(

SELECT

CONCAT(user_id,'_1') AS uid

,user_name

FROM skew_user_info_2

WHERE user_id IN (1,2)

UNION ALL

SELECT

CONCAT(user_id,'_2') AS uid

,user_name

FROM skew_user_info_2

WHERE user_id IN (1,2)

) AS tmp_b

ON tmp_a.uid = tmp_b.uid

;

其中膨胀数据的部分,我用 -- tmp_b 代替膨胀N倍的操作, 正常应该用自定义函数完成,即每一行变为N行数据

(

SELECT 

 CONCAT(user_id,'_1') AS uid

 ,user_name

FROM skew_user_info_2 

WHERE user_id IN (1,2)

UNION ALL

SELECT 

 CONCAT(user_id,'_2') AS uid

 ,user_name

FROM skew_user_info_2 

WHERE user_id IN (1,2)

) AS tmp_b



整体结果 :

SELECT

CAST(a.user_id AS STRING) AS uid

,a.user_action

,b.user_name

FROM skew_multi_action_info AS a

JOIN skew_user_info_2 AS b

ON a.user_id = b.user_id

AND a.user_id NOT IN (1,2)

AND b.user_id NOT IN (1,2)

UNION ALL

SELECT

tmp_a.uid

,tmp_a.user_action

,tmp_b.user_name

FROM

(

SELECT

CONCAT(a.user_id, '_', CAST ((RAND()*2%2 + 1) AS INT)) AS uid

,a.user_action

FROM skew_multi_action_info AS a

WHERE a.user_id IN (1,2)

) AS tmp_a

JOIN

(

SELECT

CONCAT(user_id,'_1') AS uid

,user_name

FROM skew_user_info_2

WHERE user_id IN (1,2)

UNION ALL

SELECT

CONCAT(user_id,'_2') AS uid

,user_name

FROM skew_user_info_2

WHERE user_id IN (1,2)

) AS tmp_b

ON tmp_a.uid = tmp_b.uid

;


结果

+----------+------------------+----------------+

_u1.uid  _u1.user_action  _u1.user_name 

+----------+------------------+----------------+

1_1      cc                puzheli       

1_2      pp                puzheli       

1_2      kk                puzheli       

1_1      kk                puzheli       

1_1      kk                puzheli       

1_2      kk                puzheli       

1_2      kk                puzheli       

1_1      cc                puzheli       

2_1      zz                sjz           

2_1      zz                sjz           

2_1      zz                sjz           

2_1      zS                sjz           

2_1      zS                sjz           

2_1      zS                sjz           

3        pp                xxx           

4        lp                ccc           

5        op                xdi           

+----------+------------------+----------------+

17 rows selected (27.653 seconds)

方案优点:

    对于join导致的数据倾斜,如果只是某几个key导致了倾斜,采用该方式可以用最有效的方式打散key进行join。而且只需要针对少数倾斜key对应的数据进行扩容n倍,不需要对全量数据进行扩容。避免了占用过多内存。

方案缺点:如果导致倾斜的key特别多的话,比如成千上万个key都导致数据倾斜,那么这种方式也不适合。

iii.大表与大表JOIN, 一张表数据分布均匀,另一张表大量的KEY 分布不均

目的 :使用随机前缀 和 扩容 进行 join

适用场景:如果在进行join操作时,表中有大量的key导致数据倾斜,那么进行分拆key也没什么意义,此时就只能使用最后一种方案来解决问题了。

方案实现思路:

该方案的实现思路基本和“解决方案四”类似,首先查看Hive表中的数据分布情况,找到那个造成数据倾斜的Hive表,比如有多个key都对应了超过1万条数据。

然后将该表的每条数据都打上一个n以内的随机前缀。

同时对另外一个正常的表进行扩容,将每条数据都扩容成n条数据,扩容出来的每条数据都依次打上一个0~n的前缀。

最后将两个处理后的表进行join即可。


方案优点:对join类型的数据倾斜基本都可以处理,而且效果也相对比较显著,性能提升效果非常不错。

方案缺点:

    该方案更多的是缓解数据倾斜,而不是彻底避免数据倾斜。而且需要对整个表进行扩容,对内存资源要求很高。

iiii.大表与大表JOIN, 桶表,进行表拆分

目的:增加并行度

场景:两个大表,数据分布均匀,为了提高效率,使用mapjoin,采用切分大表的方法,采用将大表切分为小表,然后进行连接

原始测试表

+----------+------------+

test.id   test.name  

+----------+------------+

1         aa        

2         bb        

3         cc        

4         dd        

+----------+------------+

将其切分为两个:

 select * from test tablesample(bucket 1 out of 2 on id);

+----------+------------+

test.id   test.name  

+----------+------------+

2         bb        

4         dd        

+----------+------------+


 select * from test tablesample(bucket 2 out of 2 on id);

+----------+------------+

test.id   test.name  

+----------+------------+

1         aa        

3         cc        

+----------+------------+

————————————————

版权声明:本文为CSDN博主「高达一号」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/u010003835/article/details/105495135

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,547评论 4 374
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,787评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,175评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,752评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,169评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,056评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,195评论 2 321
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,980评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,724评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,872评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,344评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,667评论 3 264
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,379评论 3 245
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,202评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,992评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,189评论 2 286
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,987评论 2 279

推荐阅读更多精彩内容