二本土木工程管理毕业5年,零基础转型大数据开发,收割长沙深圳多个大数据offer...

点击上方 "大数据肌肉猿"关注, 星标一起成长

点击下方链接,进入高质量学习交流群

今日更新| 1052个转型案例分享-大数据交流群

b33921e9a32cbf672f1ac4293f1b9aef.png

分享一位学习群同学的转型经历,他是二本土木类工程管理专业,17年毕业,毕业后在长沙工地从事了近5年,上半年开始学习大数据,前几个月拿了长沙和深圳多个大数据offer,后面选择了深圳一家甲方公司,目前已通过试用期,分享一些转型感受。

前言

我是普通二本的本科生,学的是工程管理专业。毕业时,工作半年左右开始仔细思考,到底想要以一个什么样的职业,融入我国发展大潮。彼时互联网风起云涌,此起彼伏互联网暴富的消息被各路媒体争相报导。

恰巧18年末在星球遇到了峰哥分享他的个人经历,于是加了他微信进了学习群,峰哥在群里分享了很多资料和经验,那时整个群基本都不是做大数据,但这几年很多人陆陆续续都转型成功了。

我最开始自学了一段时间,后来因为工作原因就停滞了,现在想想挺后悔的,要是早点转,目前薪资待遇可以更高。

今年年初因为疫情在家没法工作,在考虑了一段时间之后,就决心转大数据了。开始正式找峰哥帮忙规划学习路线和指导面试,学了几个月,年中开始面试。

最后拿到长沙一家大型制造业还有一家互联网公司,薪资在15-17W左右,拿了深圳两家外包18K,还有一家金融科技甲方19K的offer。

为什么转大数据

大数据是互联网发展的一定时期的产物。人口红利已经慢慢消失,逐渐从增量市场转向存量市场。存量市场没有增量市场那样好做,如何在现用的存量市场中更好的发展自己的企业呢?就精准营销了嘛。这就需要数据开发、数据分析、数据挖掘,产生用户画像、数据报表来为决策层决策、精准营销提供量化的依据。这正符合了“技术是演进出来的,不是想出来的”。

另外一个主要原因是工地干到头了,加上疫情原因经常停工,工作环境也比较压抑,一年干到头存不了几万块钱。

虽然今年互联网行情没有往年好,但我对比了一圈,发现还是远远比其他我能选择的行业好。

方法论

我认为先入行把技术学到手最重要,技术是程序员的核心竞争力,技术好了也就有了议价权。

在长沙

在进入一个新行业的时候,很需要有经验的过来人给到一些指导性的建议和学习方法,峰哥对我来说也就是这个过来人。

年初和峰哥详细聊了当时的个人情况,在峰哥帮我规划了学习路线和学习计划,然后就开始学了。

学的过程中,由于是接触新东西。比较吃力,心态偶尔也爆炸一下。这个时候找峰哥聊聊天。找个方式发泄一下,然后回来继续学就好了。

至于学习路线基本都是峰哥公众号分享的这些,非常赞同峰哥说的一句话:前期学习少即是多。所以前期学习并没有想象中的复杂,反而只需要学关键的一些知识点,有种四两拨千斤的感觉。

开始面试,有面试通知的话,针对JD突击学一下,面试中问面试官自己哪里不足,面试后总结。总结后继续面。面试后总结。总结后继续面。循环往复,期间和峰哥保持联系,峰哥会给到很 nice 的建议的。

就这样几个月在长沙面了几家就面试成功了,拿了两个offer,我也就去了。

公司挺大,一周五天班,朝九晚六不打卡。这就给到了我足够的时间查漏补缺,我也趁空余都在公司学习。一个月过去了,与同事交流,都感觉公司的项目没有想象中的复杂。慢慢开始意识到成长的速度似乎与一线脱节了。

干了一个多月我离职了,准备去一线工作。

在深圳

和一线的同学和前辈沟通了之后,当然也有峰哥哈。我8月份来了深圳。

然后开始投简历,面试总结调整,循环。找了将近1个月的工作,期间多次和峰哥交流面试相关的问题。刚开始拿了2个外包offer,后来又拿了金融甲方,然后就选择加入了,最近已经成功转正,感谢峰哥试用期的指导。

接下去的计划是继续精进自己的技术,在深圳多呆几年,后面回长沙选择也可以更多。

面试题摘要(整理了一些经常被问到的Hive知识点)

一、SQL 相关问题

  1. 怎么查看表结构,表创建语句?怎么查看表有哪些分区?怎么查看分区对应 hdfs 路径?

    --查看表结构信息

    desc 表名;

    --显示如何创建一个表

    show create table 表名;

    --怎么查看表有哪些分区

    hive> show partitions table_name;

    mysql>SELECT
    partition_name part,
    partition_expression expr,
    partition_description descr,
    FROM_DAYS(partition_description) lessthan_sendtime,
    table_rows
    FROM
    INFORMATION_SCHEMA.partitions
    WHERE
    TABLE_SCHEMA = SCHEMA()
    AND TABLE_NAME='el_user_category_litera'; ---这里是表名

    --hive怎么查看分区对应 hdfs 路径

    desc formatted 表名 partition (day = ‘2015-01-25′);

  2. 怎么计算某个分区的数据量大小?怎么计算某个分区的文件总数?

    列出该表的详细文件列表

    $ hadoop fs -ls /user/hive/warehouse/table_name

    --#查看分区表的容量

    $ hadoop fs -ls /user/hive/warehouse/table_name/yyyymm=201601 | awk -F ' ' '{print $5}'|awk '{a+=$1}END {print a/(1024*1024*1024)}'

    这样可以省去自己相加,下面命令是列出该表的详细文件列表

    $ hadoop fs -ls /user/hive/warehouse/table_name/yyyymm=201601

    统计文件详细数目

    $ hadoop fs -ls /user/hive/warehouse/table_name/yyyymm=201601**|wc -l**

  3. 有几种表连接(join)?

    INNER JOIN 内连接
    LEFT OUTER JOIN 左外连接
    RIGHT OUTER JOIN 右外连接
    FULL OUTER JOIN 全外连接
    LEFT SEMI JOIN 左半开连接
    JOIN笛卡尔积

    Hive查询快速查找表大小(即行数)

    ANALYZE TABLE tablename [PARTITION(partcol1[=val1], partcol2[=val2], ...)] COMPUTE STATISTICS [noscan];

    如果表被分区

    hive> ANALYZE TABLE ops_bc_log PARTITION(day) COMPUTE STATISTICS noscan;
    
    输出是
    
    分区logdata.ops_bc_log {day = 20140523} stats:[numFiles = 37,numRows = 26095186,totalSize = 654249957,rawDataSize = 58080809507]
    
    分区logdata.ops_bc_log {day = 20140521} stats:[numFiles = 30,numRows = 21363807,totalSize = 564014889,rawDataSize = 47556570705]
    
    分区logdata.ops_bc_log {day = 20140524} stats:[numFiles = 35,numRows = 25210367,totalSize = 631424507,rawDataSize = 56083164109]
    
    分区logdata.ops_bc_log {day = 20140522} stats:[numFiles = 37,numRows = 26295075,totalSize = 657113440,rawDataSize = 58496087068]
  4. 一 hive sql ,怎么计算这个 sql 会产生多少个 map 数?

    概念

    一般情况下,在输入源是文件的时候,一个task的map数量由splitSize来决定的,那么splitSize是由以下几个来决定的
    goalSize = totalSize / mapred.map.tasks
    inSize = max {mapred.min.split.size, minSplitSize}
    splitSize = max (minSize, min(goalSize, dfs.block.size))
    一个task的reduce数量,由partition决定。
    在输入源是数据库的情况下,比如mysql,对于map的数量需要用户自己指定,比如
    jobconf.set(“mapred.map.tasks.nums”,20);
    如果数据源是HBase的话,map的数量就是该表对应的region数量。

    1 map的数量

    map的数量通常是由hadoop集群的DFS块大小确定的,也就是输入文件的总块数,正常的map数量的并行规模大致是每一个Node是10~100个,对于CPU消耗较小的作业可以设置Map数量为300个左右,但是由于hadoop的每一个任务在初始化时需要一定的时间,因此比较合理的情况是每个map执行的时间至少超过1分钟。具体的数据分片是这样的,InputFormat在默认情况下会根据hadoop集群的DFS块大小进行分片,每一个分片会由一个map任务来进行处理,当然用户还是可以通过参数mapred.min.split.size参数在作业提交客户端进行自定义设置。还有一个重要参数就是mapred.map.tasks,这个参数设置的map数量仅仅是一个提示,只有当InputFormat 决定了map任务的个数比mapred.map.tasks值小时才起作用。同样,Map任务的个数也能通过使用JobConf 的conf.setNumMapTasks(int num)方法来手动地设置。这个方法能够用来增加map任务的个数,但是不能设定任务的个数小于Hadoop系统通过分割输入数据得到的值。

    2 reduece的数量

    reduce在运行时往往需要从相关map端复制数据到reduce节点来处理,因此相比于map任务。reduce节点资源是相对比较缺少的,同时相对运行较慢,正确的reduce任务的个数应该是0.95或者1.75 *(节点数 ×mapred.tasktracker.tasks.maximum参数值)。如果任务数是节点个数的0.95倍,那么所有的reduce任务能够在 map任务的输出传输结束后同时开始运行。如果任务数是节点个数的1.75倍,那么高速的节点会在完成他们第一批reduce任务计算之后开始计算第二批 reduce任务,这样的情况更有利于负载均衡。

    Hadoop在运行一个mapreduce job之前,需要估算这个job的maptask数和reducetask数。首先分析一下job的maptask数,当一个job提交时,jobclient首先分析job被拆分的split数量,然后吧job.split文件放置在HDFS中,一个job的MapTask数量就等于split的个数。

    job.split中包含split的个数由FileInputFormat.getSplits计算出,方法的逻辑如下:

    \1. 读取参数mapred.map.tasks,这个参数默认设置为0,生产系统中很少修改。

    \2. 计算input文件的总字节数,总字节数/(mapred.map.tasks==0 ? 1: mapred.map.tasks )=goalsize

    \3. 每个split的最小值minSize由mapred.min.split.size参数设置,这个参数默认设置为0,生产系统中很少修改。

    \4. 调用computeSplitSize方法,计算出splitsize= Math.max(minSize, Math.min(goalSize, blockSize)),通常这个值=blockSize,输入的文件较小,文件字节数之和小于blocksize时,splitsize=输入文件字节数之和。

    \5. 对于input的每个文件,计算split的个数。

    a) 文件大小/splitsize>1.1,创建一个split,这个split的字节数=splitsize,文件剩余字节数=文件大小-splitsize

    b) 文件剩余字节数/splitsize<1.1,剩余的部分作为一个split

    举例说明:

    \1. input只有一个文件,大小为100M,splitsize=blocksize,则split数为2,第一个split为64M,第二个为36M

    \2. input只有一个文件,大小为65M,splitsize=blocksize,则split数为1,split大小为65M

    \3. input只有一个文件,大小为129M,splitsize=blocksize,则split数为2,第一个split为64M,第二个为65M(最后一个split的大小可能超过splitsize)

    \4. input只有一个文件,大小为20M ,splitsize=blocksize,则split数为1,split大小为20M

    \5. input有两个文件,大小为100M和20M,splitsize=blocksize,则split数为3,第一个文件分为两个split,第一个split为64M,第二个为36M,第二个文件为一个split,大小为20M

    \6. input有两个文件,大小为25M和20M,splitsize=blocksize,则split数为2,第一个文件为一个split,大小为25M,第二个文件为一个split,大小为20M

    假设一个job的input大小固定为100M,当只包含一个文件时,split个数为2,maptask数为2,但当包含10个10M的文件时,maptask数为10。

    总结:

    通过map和reducetask数量的分析可以看出,hadoop/hive估算的map和reduce task数可能和实际情况相差甚远。假定某个job的input数据量庞大,reduce task数量也会随之变大,而通过join和group by,实际output的数据可能不多,但reduce会输出大量的小文件,这个job的下游任务将会启动同样多的map来处理前面reduce产生的大量文件。在生产环境中每个user group有一个map task数的限额,一个job启动大量的map task很显然会造成其他job等待释放资源。

    Hive对于上面描述的情况有一种补救措施,参数hive.merge.smallfiles.avgsize控制hive对output小文件的合并,当hiveoutput的文件的平均大小小于hive.merge.smallfiles.avgsize-默认为16MB左右,hive启动一个附加的mapreducejob合并小文件,合并后文件大小不超过hive.merge.size.per.task-默认为256MB。

    尽管Hive可以启动小文件合并的过程,但会消耗掉额外的计算资源,控制单个reduce task的输出大小>64MB才是最好的解决办法。

    map数据计算示例:
    hive> set dfs.block.size;
    dfs.block.size=268435456
    hive> set mapred.map.tasks;
    mapred.map.tasks=2
    //文件块大小为256MB,map.tasks为2

    查看文件大小和文件数:

    [dwapp@dw-yuntigw-63 hadoop]$ hadoop dfs -ls /group/alibaba-dw-icbu/hive/bdl_en12_pageview_fatdt0_d/hp_stat_date=2012-11-25;
    结果:
    Found 18 items
    -rw-r-----   3 alidwicbu cug-alibaba-dw-icbu  290700555 2012-11-26 19:00 /group/alibaba-dw-icbu/hive/bdl_en12_pageview_fatdt0_d/hp_stat_date=2012-11-25/attempt_201211151327_1675393_m_000000_0  
    -rw-r-----   3 alidwicbu cug-alibaba-dw-icbu  290695945 2012-11-26 18:59 /group/alibaba-dw-icbu/hive/bdl_en12_pageview_fatdt0_d/hp_stat_date=2012-11-25/attempt_201211151327_1675393_m_000001_0
    -rw-r-----   3 alidwicbu cug-alibaba-dw-icbu  290182606 2012-11-26 19:00 /group/alibaba-dw-icbu/hive/bdl_en12_pageview_fatdt0_d/hp_stat_date=2012-11-25/attempt_201211151327_1675393_m_000002_0
    ......

    计算:

    goalSize = 4539.059804 (文件总大小)/ mapred.map.tasks(2) = 2269.529902MB

    因此splitsize取值为256MB,所以一共分配18个map。

    若修改map.tasks参数为32
    set mapred.map.tasks = 32;

    goalSize = 4539.059804 / mapred.map.tasks(32) = 141.8456189

    因此splitsize取值为141.8MB,所以一共分配36个map。

  5. sort by、distribute by、cluster by 和 order by 区别?

    order by

    对输入做全局排序,因此只有一个Reducer。然而只有一个Reducer,会导致当输入规模较大时,消耗较长的计算时间。



    sort by

    sort by的数据只能保证在同一个reduce中的数据可以按指定字段排序。使用sort by你可以指定执行的reduce个数(通过set mapred.reduce.tasks=n来指定),对输出的数据再执行归并排序,即可得到全部结果。

    distribute by

    distribute by是控制在map端如何拆分数据给reduce端的。sort by为每个reduce产生一个排序文件。在有些情况下,你需要控制某个特定行应该到哪个reducer,这通常是为了进行后续的聚集操作。distribute by刚好可以做这件事。因此,distribute by经常和sort by配合使用。hive要求distribute by要写在sort by之前。

    cluster by

    cluster by==distribute by+sort by。但是排序只能是倒叙排序,不能指定排序规则为ASC或者DESC。

    注:Distribute by和sort by的使用场景

    **1.**Map输出的文件大小不均。

    **2.**Reduce输出文件大小不均。

    **3.**小文件过多。

    **4.**文件超大。

    hive (hive)> select * from temperature distribute by year sort by year asc,tempra desc;
  6. a 表和 b 表内连接,a表为小表,只有2000 行记录,可以进行怎么样的优化?select a.* from a join b on a.key=b.key;

    可以让hive自动识别,把join变成合适的Map Join如下所示

    注:当设置为true的时候,hive会自动获取两张表的数据,判定哪个是小表,然后放在内存中

    set hive.auto.convert.join=true;
    select a.* from a join b on a.key=b.key;
  7. a表 left join b 表,b表为小表,可以进行怎么样的优化?select a.* from a left join b on a.key=b.key;

  8. 两大表连接,发生了数据倾斜,有几个 reduce 无法完成,怎么查找发生数据倾斜的原因?怎么优化?

  9. 每天图书馆的人流量信息被记录在这三列信息中:序号(id)、日期(date)、人流量(people)。请编写一个查询语句,找出高峰期时段,要求连续三天及以上,并且每天人流量均不少于100。

    PS:每天只要一行记录,日期随 id 的增加而增加。

    表table_1

id

date

people




1

2017-01-01

10

2

2017-01-02

109

3

2017-01-03

150

4

2017-01-04

99

5

2017-01-05

145

6

2017-01-06

1455

7

2017-01-07

199

8

2017-01-08

188

输出为

id

date

people




5

2017-01-05

145

6

2017-01-06

1455

7

2017-01-07

199

8

2017-01-08

188

答案:

如果只是找出全部人流量不少于100的记录不难,难点在于如何查找连续的三天,一个想法是,查 3 张表,让三个结果 id 连续

SELECT a.*
FROM stadium as a,stadium as b,stadium as c
where (a.id = b.id-1 and b.id+1 = c.id) 
  and (a.people>=100 and b.people>=100 and c.people>=100);

但是这样输出会有问题,比如 5,6,7,8 号人流量不少于100,但是只输出了 5,6号,根本原因在于,我们将 a 的 id 设为三个连续值中最小值,所以只返回了每 3 个连续值中最小的一个,同理可想到,我们再将 a 的 id 设为三个连续值中中间值和最大值,可以得到全部的连续 3 个值

SELECT a.*
FROM stadium as a,stadium as b,stadium as c
where ((a.id = b.id-1 and b.id+1 = c.id) or
       (a.id-1 = b.id and a.id+1 = c.id) or
       (a.id-1 = c.id and c.id-1 = b.id))
  and (a.people>=100 and b.people>=100 and c.people>=100);

但是这样还有个问题,比如 5,6,7,8,6 既是 5,6,7 的中间值也是 6,7,8 的最小值,所以还要去重,也许 id 不按序排列,再排序 id,最终得到答案

SELECT distinct a.*
FROM stadium as a,stadium as b,stadium as c
where ((a.id = b.id-1 and b.id+1 = c.id) or
       (a.id-1 = b.id and a.id+1 = c.id) or
       (a.id-1 = c.id and c.id-1 = b.id))
  and (a.people>=100 and b.people>=100 and c.people>=100)
order by a.id;

链接:https://leetcode-cn.com/problems/human-traffic-of-stadium/solution/ti-yu-guan-de-ren-liu-liang-by-little_bird/
来源:力扣(LeetCode)

二、Join 优化

实际生产环境中,一天的数据可能有50G

MapJoin(大表对小表)
  • 设置:

    可以让hive自动识别,把join变成合适的Map Join如下所示

    注:当设置为true的时候,hive会自动获取两张表的数据,判定哪个是小表,然后放在内存中

set hive.auto.convert.join=true;
select /*+ MAPJOIN(time_dim) */ count(*) from store_sales join time_dim on (ss_sold_time_sk = t_time_sk)

大表对大表,既然是两个表进行join,肯定有相同的字段吧。

set hive.auto.convert.sortmerge.join=true
set hive.optimize.bucketmapjoin=true;
set hive.optimize.bucketmapjoin.sortedmerge=true;
BUCKET MAP JOIN

Map Join 效率比 Common Join 效率好,但总会有“小表”条件不满足的时候。这就需要 bucket map join 了。

Bucket map join 需要待连接的两个表在连接字段上进行分桶(每个分桶对应hdfs上的一个文件),而且小表的桶数需要时大表桶数的倍数。

建立分桶表的例子:

CREATE TABLE my_user
(uid INT,
 name STRING)
CLUSTERED BY (uid) into 32 buckets
STORED AS TEXTFILE;

这样,my_user 表就对应 32 个桶,数据根据 uid 的 hash value 与32 取余,然后被分发导不同的桶中。

如果两个表在连接字段上分桶,则可以执行 bucket map join 了,具体的:

设置属性 hive.optimize.bucketmapjoin= true 控制 hive 执行 bucket map join;
对小表的每个分桶文件建立一个 hashtable,并分发到所有做连接的 map端;
map 端接受了N(N为小表分桶的个数) 个小表的 hashtable,做连接操作的时候,只需要将小表的一个 hashtable 放入内存即可,然后将大表的对应的 split 拿出来进行连接,所以其内存限制为小表中最大的那个hashtable 的大小。

SORT MERGE BUCKET MAP JOIN

对于 bucket map join 中的两个表,如果每个桶内分区字段也是有序的,则还可以进行 sort merge bucket map join。

建表语句为:

CREATE TABLE my_user
( uid INT,
  name STRING)
CLUSTERED BY (uid) SORTED BY (uid) into 32 buckets
STORED AS TEXTFILE;

这样一来当两边 bucket 要做局部 join 的时候,只需要用类似 merge sort 算法中的 merge 操作一样把两个 bucket 顺序遍历一遍即可完成,小表的数据可以每次只读取一部分,然后还是用大表一行一行的去匹配,这样的join 没有限制内存的大小. 并且也可以执行全外连接。
进行sort merge bucket map join时,需要设置的属性为:

set hive.optimize.bucketmapjoin= true;
set hive.optimize.bucketmapjoin.sortedmerge = true;
set hive.input.format = org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
JOIN 的对比

JOIN类型

优点

缺点




COMMON JOIN

可以完成各种 JOIN 操作,不受表大小和表格式的限制

无法只在 map 端完成 JOIN 操作,耗时长,占用更多地网络资源

MAP JOIN

可以在 map 端完成 JOIN 操作,执行时间短

待连接的两个表必须有一个“小表”,“小表”必须加载内存中

BUCKET MAP JOIN

可以完成 MAP JOIN,不受“小表”限制

表必须分桶,做连接时小表分桶对应 hashtable 需要加载到内存

SORT MERGE BUCKET MAP JOIN

执行时间短,可以做全连接,几乎不受内存限制

表必须分桶,而且桶内数据有序

三、数据倾斜处理

数据倾斜可能会发生在group过程和join过程。

• 数据倾斜症状:
任务长时间维持在99%(或100%);
查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成;
本地读写数据量很大。
• 原因:
key分布不均匀;
业务数据本身特点。
• 导致数据倾斜的操作:
GROUP BY, COUNT DISTINCT(),join
————————————————
版权声明:本文为CSDN博主「login_sonata」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/login_sonata/article/details/75000766

大表和小表关联

  1. 多表关联时,将小表(关联键重复记录少的表)依次放到前面,这样可以触发 reduce 端更少的操作次数,减少运行时间。

  2. 同时可以使用 Map Join 让小的维度表缓存到内存。在map端完成join过程,从而省略掉redcue端的工作。但是使用这个功能,需要开启map-side join的设置属性:set hive.auto.convert.join=true(默认是false)

    同时还可以设置使用这个优化的小表的大小:set hive.mapjoin.smalltable.filesize=25000000(默认值25M)
    ————————————————
    原文链接:https://blog.csdn.net/qq_26442553/article/details/80866723

大表和大表的关联

大表与大表关联,如果其中一张表的多是空值或者 0 比较多,容易 shuffle 给一个reduce,造成运行慢。

这种情况可以对异常值赋一个随机值来分散 key,均匀分配给多个 reduce 去执行,比如:

select *
  from log a
  left outer join users b
  on case when a.user_id is null then concat('hive',rand() ) else a.user_id end = b.user_id;

-- 将A表垃圾数据(为null)赋一个随机的负数,然后将这些数据shuffle到不同reduce处理。

当 key 值都是有效值时,解决办法为:

设置以下参数:

# 每个节点的 reduce 默认是处理 1G 大小的数据
set hive.exec.reducers.bytes.per.reducer = 1000000000 
# 如果 join 操作也产生了数据倾斜,可以设定
set hive.optimize.skewjoin = true;
set hive.skewjoin.key = skew_key_threshold (default = 100000)

Hive 在运行的时候无法判断哪个 key 会产生倾斜,所以使用 hive.skewjoin.key 参数控制倾斜的阈值,如果超过这个值,新的值会发送给那些还没有达到的 reduce,一般可以设置成待处理的总记录数/reduce 个数的 2-4 倍。

其他情况数据倾斜的处理

解决方式1:

hive.map.aggr=true (默认true) 这个配置项代表是否在map端进行聚合,相当于Combiner

hive.groupby.skewindata=true(默认false)

似乎是解决数据倾斜的万能钥匙,查询计划会有两个 MR Job,第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。

通用的一些数据倾斜的处理方法

1.reduce个数太少

reduce数太少set mapred.reduce.tasks=800;

默认是先设置hive.exec.reducers.bytes.per.reducer这个参数,设置了后hive会自动计算reduce的个数,因此两个参数一般不同时使用

2.当HiveQL中包含count(distinct)时
如果数据量非常大,执行如select a,count(distinct b) from t group by a;类型的SQL时,会出现数据倾斜的问题。

解决方法:使用sum...group by代替。如select a,sum(1) from (select a, b from t group by a,b) group by a;

--end--

扫描下方二维码

添加好友,备注【交流】
可围观朋友圈,也可私信交流
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值