hive 常见调优方式(从入门到精通 看这一篇就够了)

1-常见优化手段

1.1 分桶表基本介绍

  • 分桶表:
    • 分文件的, 在创建表的时候, 指定分桶字段, 并设置分多少个桶, 在添加数据的时候, hive会根据设置分桶字段, 将数据划分到N个桶(文件)中, 默认情况采用HASH分桶方案 , 分多少个桶, 取决于建表的时候, 设置分桶数量, 分了多少个桶最终翻译的MR也就会运行多少个reduce程序(HIVE的分桶本质上就是MR的分区操作)
    • 如何构建一个分桶表呢?
create table 表名(
    字段 类型,
    ....
)
clustered by(分桶字段) [sorted by (字段 [asc | desc])] into N buckets   --- 定义分桶表核心语句
row format......
  • 如何向桶表添加数据
load data [local] inpath  '文件路径' into table 表名; 

思考:  当前项目是否可以通过  load  data 方式添加数据呢? 不行的
注意: 如果在 apache 版本,使用HIVE, 默认情况下, 是可以通过 load data 方式来加载数据,会生成分桶文件!!!
    
但是对于 CDH版本中, 是不允许通过 load data 方式来加载的: 
在CDH中默认开启了一个参数, 禁止采用load data方式向桶表添加数据:set hive.strict.checks.bucketing = true;
如果想要load data 能够使用需要关闭:set hive.strict.checks.bucketing = false;
      注意: 如果关闭后,只是普通的移动,不会生成分桶文件
      

现有cdh hive2 环境,如果 现有一个文本文件数据, 需要加载到分桶表,如何解决呢? 
   第一步: 基于桶表创建一张临时表, 此表和桶表保持相同字段, 唯一区别, 当前这个表不是一个桶表
   第二步: 将数据先加载到这个临时表中
   第三步: 基于临时表, 使用 insert into|overwrite + select 将数据添加到桶表   
  • 桶表有什么用呢?
1) 进行数据采样工作
    1.1) 当表的数据量比较庞大的时候, 在编写SQL语句后, 需要首先测试 SQL是否可以正常的执行,  需要在表中执行查询操作, 由于表数据量比较庞大, 在测试一条SQL的时候整个运行的时间比较久, 为了提升测试效率, 可以整个表抽样出一部分的数据, 进行测试
    1.2) 校验数据的可行性(质量校验)
    1.3) 进行统计分析的时候, 并不需要统计出具体的指标, 可能统计的都是一些相对性指标, 比如说一些比率(合格率)问题, 此时可以通过采样处理
  

2) 提升查询的效率(更主要是提升JOIN的效率)
    可以减少JOIN次数, 从而提升效率
    
注意:
    在生产环境中, 何时使用桶表, 主要看是否需要应用上述作用

2

1.2 数据采样

采样函数: 
    tablesample(bucket x out of y [on column|rand()])
    
使用位置:  查询的时候,紧紧跟在表名的后面, 如果表名有别名, 必须放置别名的前面

普通表:
说明:
    x: 从第几份进行采样, x 不能大于 y
    y: 直接把表临时分几份
    column: 分桶的字段, 可以省略
    

分桶表: 前提已经提前创建,并且生成了n个桶文件
说明:
    x: 从第几个桶开始进行采样,  x 不能大于 y
    y: 把n个桶文件分几份   也就是抽样比例n/y     y必须是桶表的分桶数量的倍数或者因子
    column: 分桶的字段, 可以省略
   

分桶表抽样案例: 
    1) 假设 A表有10个桶, 请分析, 下面的采样函数, 会将那些桶抽取出来呢?
        tablesample(bucket 2 out of 5 on xxx) 
        
        会抽取出几个桶数据呢?   总桶数 / 抽样比例 =  分桶数量     2个桶
        抽取那几个桶呢?   (x + y)
            2 , 7          
            000001_0 , 000006_0
    
   2) 假设 A 表有20个桶, 请分析, 下面的抽样函数, 会将那些桶抽取出来呢?
       tablesample(bucket 4 out of 4 on xxx)  
       
       会抽取出几个桶数据呢?  总桶数 / 抽样比例 =  分桶数量   5个桶
       抽取那几个桶呢? 
           4, 8,12,16,20
           000003_0,000007_0,0000011_0,0000015_0,0000019_0
       tablesample(bucket 8 out of 40 on xxx)  
       
       会抽取出几个桶数据呢? 总桶数 / 抽样比例 =  分桶数量  二分之一个桶
       抽取那几个桶呢?
           8桶二分之一       
           000007_0的一半数据
           
   
   大多数情况下, 都是因子, 取某几个桶的操作

1.3 Join优化操作

思考: 在执行Join的SQL的时候, SQL会被翻译为MR, 思考, 翻译后MR默认是如何进行JOIN操作的呢?

在这里插入图片描述

思考: 这种reduce端Join操作, 存在那些弊端呢? 
1- 可能会存在数据倾斜的问题 (某几个reduce接收数据量远远大于其他的reduce接收数据量)
2- 所有的数据处理的操作, 全部都压在reduce中进行处理, 而reduce数量相比Map来说少的多,导致整个reduce压力比较大

思考: 如何提升Join的效率呢? 思路: 能否不让reduce做这个聚合处理的事情, 将这项工作尝试交给mapTask

1.3.1 Map Join

在这里插入图片描述

Map Join: 每一个mapTask在读取数据的时候, 每读取一条数据, 就会和内存中班级表数据进行匹配, 如果能匹配的上, 将匹配上数据合并在一起, 输出即可

好处: 将原有reduce join 问题全部都可以解决

弊端: 
    1- 比较消耗内存
    2- 要求整个 Join, 必须的都有一个小表, 否则无法放入到内存中

仅适用于: 小表 join 大表 | 大表 join 小表   
    在老版本(1.x以下), 需要将小表放置在前面, 大表放置在后面, 在新版本中, 无所谓
    建议, 如果明确知道那些表示小表, 可以优先将这些表, 放置在最前面

如何使用呢? 
-- map join
set hive.auto.convert.join=true; -- 开启 map join的支持  默认值为True
set hive.mapjoin.smalltable.filesize= 25000000;  --设置 小表的文件大小(23.84m)
set hive.auto.convert.join.noconditionaltask.size=20971520; -- 设置 join任务数据量

如果不满足条件, HIVE会自动使用 reduce join 操作
1.3.2 Bucket Map Join
  • 适用场景: 中型表 和 大表 join:
    • 方案一: 如果中型表能对数据进行提前过滤, 尽量提前过滤, 过滤后, 有可能满足了Map Join 条件 (并不一定可用)
    • 方案二: Bucket Map Join
-- bucket map  join
set hive.optimize.bucketmapjoin; -- 默认false
/*
    1- Join两个表必须是分桶表
    2- 开启 Bucket Map Join 支持:  set hive.optimize.bucketmapjoin = true;
    3- 一个表的分桶数量是另一个表的分桶数量的整倍数
    4- 分桶列 必须 是 join的ON条件的列
    5- 必须建立在Map Join场景中(中型表是小表的3倍, 此时分至少3个桶)
*/

在这里插入图片描述

1.3.3 SMB Join
  • 适用场景: 大表 和 大表 join
  • 解决方案: SMB Join ( sort merge bucket map join)
-- 使用条件:
--     1- 两个表必须都是分桶表
--     2- 开启 SMB Join 支持:
        set hive.auto.convert.sortmerge.join; -- 默认false
        set hive.optimize.bucketmapjoin.sortedmerge ;-- 默认false
        set hive.auto.convert.sortmerge.join.noconditionaltask;--  Hive 0.13.0默认开启
--    3- 两个表的分桶的数量是一致的
--    4- 分桶列 必须是 join的 on条件的列, 同时必须保证按照分桶列进行排序操作
       -- 开启强制排序
       set hive.enforce.sorting; -- hive2.x移除 默认true
       -- 在建分桶表使用: 必须使用sorted by()

--    5-  应用在Bucket Map Join 场景中
       -- 开启 bucket map join
       set hive.optimize.bucketmapjoin ; --默认false
       

一般来说:

事实表 + 低基数的维度表 进行关联: Map Join 优化
事实表 + 高基数的维度表 进行关联: Bucket Map Join 优化
事实表 + 事实表 进行关联: SMB Join 优化(相对使用最少, 因为条件过于苛刻, 而且对资源消耗过大, 如果资源不够, 运行效率低于原始Join方案)

思考: 讲上面的目的是什么? 
尝试在数仓中, 找到可以匹配的地方, 在面试的时候, 可以在这个位置中讲解对应的优化

建议: Join优化集中在DWD和DWM层进行优化讲解

1.4 HIVE的索引

索引有什么用呢? 用于提升查询的效率

为什么说, 索引可以提升查询的效率呢? 思想性

在这里插入图片描述

1.4.1 HIVE原始索引(废弃)
hive的原始索引可以针对某个列, 或者某几列构建索引信息, 构建后提升查询执行列的查询效率
    
存在弊端: hive原始索引不会自动更新,每次表中数据发生变化后, 都是需要手动重建索引操作, 比较耗费时间和资源, 整体提升性能一般
       
所以在HIVE3.x版本后, 已经直接将这种索引废弃掉了, 无法使用, 而且官方描述在hive1.x 和 hive2.x版本中, 也不建议优先使用原始索引
1.4.2 ORC相关索引

ORC的全称是(Optimized Record Columnar),使用ORC文件格式可以提高hive读、写和处理数据的能力。
​ 在ORC格式的hive表中,记录首先会被横向的切分为多个stripes,然后在每一个stripe内数据以列为单位进行存储,所有列的内容都保存在同一个文件中。每个stripe的默认大小为256MB,相对于之前RCFile每个4MB而言,更大的stripe使ORC的数据读取更加高效。
ORC在RCFile的基础上进行了一定的改进,所以与RCFile相比,具有以下一些优势:
1、ORC中的特定的序列化与反序列化操作可以使ORC file writer根据数据类型进行写出。
2、提供了多种RCFile中没有的indexes,这些indexes可以使ORC的reader很快的读到需要的数据,并且跳过无用数据,这使得ORC文件中的数据可以很快的得到访问。
3、由于ORC file writer可以根据数据类型进行写出,所以ORC可以支持复杂的数据结构(比如Map等)。
4、除了上面三个理论上就具有的优势之外,ORC的具体实现上还有一些其他的优势,比如ORC的stripe默认大小更大,为ORC writer提供了一个memory manager来管理内存使用情况。

Row Group Index索引

row group index: 行组索引 (又叫最小最大索引)

条件: 
    1) 要求表的存储类型为ORC存储格式
    2) 在创建表的时候, 必须开启 row group index 索引支持
        'orc.create.index'='true'
    3) 在插入数据的时候, 必须保证需求进行索引列, 按序插入数据

适用于: 数值类型的, 并且对数值类型进行 >  <  >=  <=操作

思路: 
    插入数据到ORC表后, 会自动进行划分为多个script片段, 每个片段内部, 会保存着每个字段的最小, 最大值, 这样, 当执行查询 > < = 的条件筛选操作的时候, 根据最小最大值锁定相关的script片段, 从而减少数据扫描量, 提升效率
    
操作: 
    CREATE TABLE lxw1234_orc2 (字段列表 ....) stored AS ORC 
    TBLPROPERTIES ( 
      'orc.compress'='SNAPPY', 
      -- 开启行组索引 
      'orc.create.index'='true' 
    )
    
    插入数据的时候, 需要保证数据有序的
    insert overwrite table lxw1234_orc2
    SELECT  id, pcid FROM lxw1234_text 
    -- 插入的数据保持排序(可以使用全局排序, 也可以使用局部排序, 只需要保证一定有序即可, 建议使用局部排序, 插入数据效率高一些, 因为全局排序只有一个reduce) 
    DISTRIBUTE BY id sort BY id;
    
使用: 
    set hive.optimize.index.filter; -- 默认true
    SELECT COUNT(1) FROM lxw1234_orc1 WHERE id >= 1382 AND id <= 1399;
Bloom Fliter Index索引

bloom filter index (布隆过滤索引): 布隆过滤器

条件: 
    1) 要求表的存储类型为 ORC存储方案
    2) 在建表的时候, 必须设置为那些列构建布隆索引
    3) 仅能适合于等值过滤查询操作
 
思路: 
    在开启布隆过滤索引后, 可以针对某个列, 或者某几列来建立索引, 构建索引后, 会将这一列的数据的值存储在对应script片段的索引信息中, 这样当进行 等值查询的时候, 首先会到每一个script片段的索引中, 判断是否有这个值, 如果没有, 直接跳过script, 从而减少数据扫描量, 提升效率
    
  
操作:  
    CREATE TABLE lxw1234_orc2 (字段列表....)
    stored AS ORC 
    TBLPROPERTIES ( 
      'orc.compress'='SNAPPY', 
      -- 开启 行组索引 (可选的, 支持全部都打开, 也可以仅开启一个)
      'orc.create.index'='true', 
      -- pcid字段开启BloomFilter索引 
      'orc.bloom.filter.columns'='pcid,字段2,字段3...'
    )
    
    插入数据: 没有要求, 当然如果开启行组索引, 可以将需要使用行组索引的字段, 进行有序插入即可
    
使用:
    set hive.optimize.index.filter; -- 默认true
    SELECT COUNT(1) FROM lxw1234_orc1 
    WHERE id >= 0 AND id <= 1000 -- 底层用了行组索引
    AND pcid IN ('001','002');  -- 底层用了布隆过滤索引

在什么时候可以使用呢?

1- 对于行组索引: 我们建议只要数据存储格式为ORC, 建议将这种索引全部打开, 至于导入数据的时候, 如果能保证有序, 那最好, 如果保证不了, 也无所谓, 大不了这个索引的效率不是特别好

2- 对于布隆过滤索引: 建议将后续会大量的用于等值连接的操作字段, 建立成布隆索引, 比如说: JOIN的字段  经常在where后面出现的等值连接字段

1.5 如何解决数据倾斜问题

1.5.1 Join数据倾斜

在前序讲解reduce 端 JOIN的时候, 描述过reduce 端Join的问题, 其中就包含reduce端Join存在数据倾斜的问题

解决方案一:
Map Join (默认开启), 
Bucket Map Join(默认关闭,条件是分桶表,且数量是倍数关系) , 
SMB Join(条件是分桶表,且桶数量必须一致,插入数据的时候要排序)
    
注意:  
   通过 Map Join,Bucket Map Join,SMB Join 来解决数据倾斜, 但是 这种操作是存在使用条件的, 如果无法满足这些条件,  无法使用 这种处理方案
解决方案二:
思路:  将那些产生倾斜的key和对应v2的数据, 从当前这个MR中移出去, 单独找一个MR来处理即可, 处理后, 和之前的MR进行汇总结果即可

关键问题:  如何找到那些存在倾斜的key呢?  特点: 这个key数据有很多

1.运行期处理方案:
    思路: 在执行MR的时候, 会动态统计每一个 k2的值出现重复的次数, 当这个重复的次数达到一定的阈值后, 认为当前这个k2的数据存在数据倾斜, 自动将其剔除, 交由给一个单独的MR来处理即可,两个MR处理完成后, 将结果基于union all 合并在一起即可
    
    实操:  
        set hive.optimize.skewjoin=true;  -- 开启运行期处理倾斜参数默认false
        set hive.skewjoin.key=100000;   -- 阈值,  此参数在实际生产环境中, 需要调整在一个合理的值(否则极易导致大量的key都是倾斜的),默认100000
            判断依据: 查看 join的 字段 对应重复的数量有多少个, 然后选择一个合理值
              比如判断:  id为 1  大概有 100w  id为 2 88w  id 为 3 大概有 500w   设置阈值为 大于500w次数据
               或者: 总数量大量1000w, 然后共有 1000个班级, 平均下来每个班级数量大概在 1w条, 设置阈值:  大于 3w条 ~5w条范围 (超过3~5倍才认为倾斜)
        
    
    适用于: 并不清楚那个key容易产生倾斜, 此时交由系统来动态检测

2.编译期处理方案: 
    思路1:  在创建这个表的时候, 我们就可以预知到后续插入到这个表中数据, 那些key的值会产生倾斜, 在建表的时候, 将其提前配置设置好即可, 在后续运行的时候, 程序会自动将设置的key的数据单独找一个MR来进行处理即可, 处理完成后, 再和原有结果进行union all 合并操作
    
    实操1:  
        set hive.optimize.skewjoin.compiletime=true;  -- 开启编译期处理倾斜参数
        
        CREATE TABLE list_bucket_single (key STRING, value STRING) 
        -- 倾斜的字段和需要拆分的key值 
        SKEWED BY (key) ON (1,5,6) 
        -- 为倾斜值创建子目录单独存放 
        [STORED AS DIRECTORIES];
        
      思路2: 大量的key可以拼接rand()  
      实操2: 举例: 如果大量相同的男,可以拼接随机数: concat('男',rand())

    适用于:  提前知道那些key存在倾斜
    
在实际生产环境中, 应该使用那种方式呢?   两种方式都会使用的
    一般来说, 会将两个都开启, 编译期的明确在编译期将其设置好, 编译期不清楚, 通过运行期动态捕获即可

底层union all 优化方案

说明: 不管是运行期 还是编译期的join倾斜解决, 最终都会运行多个MR, 将多个MR结果通过union all 进行汇总, union all也是需要单独一个MR来处理
    
解决方案: 
        让每一个MR在运行完成后, 直接将结果输出到目的地即可, 默认 是各个MR将结果输出临时目录, 通过 union all 合并到最终目的地
         
        开启此参数即可: 
        set hive.optimize.union.remove=true;
1.5.2 group by 数据倾斜
  • 为什么在group by 的时候, 可能会出现倾斜的问题呢?
假设目前有这么一个表:  

sid       sname    cid
s01       张三     c01
s02       李四     c02
s03       王五     c01
s04       赵六     c03
s05       田七     c02
s06       周八     c01
s07       李九     c01
s08       老王     c04

需求: 请计算每个班级有多少个人
select  cid,count(1) as total  from  stu  group by  cid;

翻译后MR是如何处理SQL呢?

MAP 阶段: 假设Map阶段跑了二个MapTask

    mapTask1:
        k2          v2
        c01        {s01       张三     c01}
        c02        {s02       李四     c02}
        c01        {s03       王五     c01}
        c03        {s04       赵六     c03}
    mapTask2:
        k2          v2
        c02        {s05       田七     c02}
        c01        {s06       周八     c01}
        c01        {s07       李九     c01}
        c04        {s08       老王     c04}



reduce阶段: 假设reduceTask有二个

    reduceTask1: 接收 c01 和 c02的数据
      接收数据
         k2        v2
        c01        {s01       张三     c01}
        c02        {s02       李四     c02}
        c01        {s03       王五     c01}
        c02        {s05       田七     c02}
        c01        {s06       周八     c01}
        c01        {s07       李九     c01}

      分组后:
        c01      [{s01       张三     c01},{s03       王五     c01},{s06       周八     c01},{s07       李九     c01}]
        c02      [{s02       李四     c02},{s05       田七     c02}]

      结果数据: 
        c01     4
        c02     2

    reduceTask2: 接收 c03 和 c04的数据
      接收数据
         k2        v2
        c03        {s04       赵六     c03}
        c04        {s08       老王     c04}

      分组后:
        c03        [{s04       赵六     c03}]
        c04        [{s08       老王     c04}]

      结果数据:
        c03     1
        c04     1

在以上整个计算流程中, 发现 其中一个reduce接收到的数据量比另一个reduce接收的数据量要多的多, 认为出现了数据倾斜的问题, 所以group by 也有可能产生数据倾斜

思考: 如何解决group by的数据倾斜呢?

解决方案一:
  • MR的 combiner(规约, 提前聚合) 减少数据达到reduce数量, 从而减轻倾斜问题

    默认开启 set hive.map.aggr=true;

假设目前有这么一个表:  

sid       sname    cid
s01       张三     c01
s02       李四     c02
s03       王五     c01
s04       赵六     c03
s05       田七     c02
s06       周八     c01
s07       李九     c01
s08       老王     c04

需求: 请计算每个班级有多少个人
select  cid,count(1) as total  from  stu  group by  cid;

翻译后MR是如何处理SQL呢?

MAP 阶段: 假设Map阶段跑了二个MapTask
    mapTask1:
        k2          v2
        c01        {s01       张三     c01}
        c02        {s02       李四     c02}
        c01        {s03       王五     c01}
        c03        {s04       赵六     c03}
    规约(提前聚合)操作: 处理逻辑与reduce处理逻辑一致
      分组: 
         c01    [{s01       张三     c01},{s03       王五     c01}]  
         c02    [{s02       李四     c02}]
         c03    [{s04       赵六     c03}]
      提前聚合得出结果:
          c01     2
          c02     1
          c03     1
    mapTask2:
        k2          v2
        c02        {s05       田七     c02}
        c01        {s06       周八     c01}
        c01        {s07       李九     c01}
        c04        {s08       老王     c04}
    规约(提前聚合)操作: 处理逻辑与reduce处理逻辑一致
      分组: 
         c01    [{s06       周八     c01},{s07       李九     c01}]  
         c02    [{s05       田七     c02}]
         c04    [{s08       老王     c04}]
     提前聚合得出结果:
          c01     2
          c02     1
          c04     1


reduce阶段: 假设reduceTask有二个
    reduceTask1: 接收 c01 和 c02的数据
      接收数据
         k2        v2
         c01       2
         c02       1
         c01       2
         c02       1    
      分组后:
        c01      [2,2]
        c02      [1,1]  
      结果数据: 
        c01     4
        c02     2 
    reduceTask2: 接收 c03 和 c04的数据
      接收数据
         k2        v2
         c03       1
         c04       1 
      分组后:
        c03        [1]
        c04        [1]
      结果数据:
        c03     1
        c04     1  
  
 通过规约来解决数据倾斜, 处理完成后, 发现 两个reduce中从原来相差 3倍, 变更为相差 2倍, 减轻了数据倾斜问题
 
 
 如何配置呢? 
     只需要在HIVE中开启combiner提前聚合配置参数即可:  
         set hive.map.aggr=true;
解决方案二:
  • 负载均衡的解决方案(需要运行两个MR来处理) (大combiner方案)

    默认关闭,如果需要,手动开启 set hive.groupby.skewindata=true;

假设目前有这么一个表:  

sid       sname    cid
s01       张三     c01
s02       李四     c02
s03       王五     c01
s04       赵六     c03
s05       田七     c02
s06       周八     c01
s07       李九     c01
s08       老王     c04

需求: 请计算每个班级有多少个人
select  cid,count(1) as total  from  stu  group by  cid;

翻译后MR是如何处理SQL呢?

第一个MR的操作: 对数据进行打散
Map 阶段:  假设运行了两个MapTask
    mapTask1:
        k2          v2
        c01        {s01       张三     c01}
        c02        {s02       李四     c02}
        c01        {s03       王五     c01}
        c03        {s04       赵六     c03}
    mapTask2:
        k2          v2
        c02        {s05       田七     c02}
        c01        {s06       周八     c01}
        c01        {s07       李九     c01}
        c04        {s08       老王     c04}  

mapTask执行完成后, 在进行分发数据到达reduce, 默认情况下将相同k2的数据发往同一个reduce, 目前采用方案为随机分发, 保证每一个reduce拿到相等数量的数据信息(负载过程, 让每一个reduce接收到相同数量的数据)

reduce阶段: 假设有两个reduceTask

    reduceTask1:
        接收到数据:  
            c01        {s01       张三     c01}
            c01        {s03       王五     c01}
            c01        {s06       周八     c01}
            c01        {s07       李九     c01}
        分组操作: 
            c01    [{s01       张三     c01},{s03       王五     c01},{s06       周八     c01},{s07       李九     c01}]     
        输出结果: 
            c01     4
    reduceTask2:
        接收到数据:
            c03        {s04       赵六     c03}
            c02        {s05       田七     c02}
            c02        {s02       李四     c02}
            c04        {s08       老王     c04}

        分组操作: 
            c03        [{s04       赵六     c03}]
            c02        [{s02       李四     c02},{s05       田七     c02}]
            c04        [{s08       老王     c04}]

        输出结果:
            c02     2
            c03     1
            c04     1
            
负载均衡解决:
第一个MR执行完成了, 随机打乱分配,假设每个reduce都接收到四条数据, 自然也就不存在数据倾斜的问题了

第二个MR进行处理:  严格按照相同k2发往同一个reduce

Map 阶段:  假设有二个mapTask
    mapTask1:  
        k2      v2
        c01     2
        c02     2
    mapTask2:
        k2      v2
        c01     2
        c03     1
        c04     1
reduce阶段:   假设有两个reduce
    reduceTask1: 接收 c01 和 c02 数据
      接收数据:  
         k2     v2
         c01     4
         c02     2
      结果:
         c01    4
         c02    2
    reduceTask2: 接收 c03 和c04
      接收数据:  
         k2     v2
         c03     1
         c04     1 
      结果:
         c03     1
         c04     1


通过负载均衡方式来解决数据倾斜, 同样也可以减轻数据倾斜的压力


细细发现, 方案一 和 方案二, 是有类似之处的, 方案一, 让每一个mapTask内部进行提前聚合, 然后到达reduce进行汇总合并得出结构, 方案二: 让第一个MR进行打散并对数据进行聚合计算 得出局部结果, 然后让第二个MR进行最终聚合计算操作, 得出最终结果


说明: 方案二, 比方案一, 更能彻底解决数据倾斜问题, 因为其处理数据范围更大, 整个整个数据集来处理, 而方案一, 只是每个MapTask处理, 仅仅局部处理

如何使用方案二: 
    只需要开启负载均衡的HIVE参数配置即可:
        set hive.groupby.skewindata=true;

这两种方式:  建议在生产中, 优先使用第一种, 如果第一种无法解决, 尝试使用第二种解决


注意事项:   使用第二种负载均衡的解决group by 的数据倾斜, 一定要注意, SQL语句中不能出现多次  distinct操作, 否则 HIVE会直接报错的
    错误信息: 
        Error in semantic analysis: DISTINCT on different columns not supported with skew in data.
    比如说: 
        SELECT ip, count(DISTINCT uid), count(DISTINCT uname) FROMlog GROUP BY ip   此操作就直接报错了,只能使用方案一解决数据倾斜

倾斜的参数配置开启条件, 一定是出现了数据倾斜的问题, 如果没有出现 不需要开启的

查找是否倾斜

思考: 如何才能知道发生了数据倾斜呢?

 倾斜发生后, 出现的问题, 程序迟迟无法结束, 或者说翻译的MR中reduceTask有多个, 大部分的reduceTask都执行完成了, 只有其中一个或者几个没有执行完成, 此时认为发生了数据倾斜
    
    
    关键点: 如何查看每一个reduceTask执行时间
  • 方式: 通过Yarn查看(运行过程中) 或者 jobhistory查看(已经结束的程序) (此操作, 只能在本地演示查看, 云端环境没有开启yarn端口, 无法查看的)

在这里插入图片描述

运行的时候点击:

在这里插入图片描述在这里插入图片描述

目前, 我们这里可能只有一个reduce, 但是实际上生产环境中, 此位置可能会有多个reduceTask, 我们需要观察每个reduceTask执行时间, 如果发现其中一个或者几个reduce执行时间, 远远大于其他的reduceTask执行时间, 那么说明存在数据倾斜的问题

如果程序以及运行完成了, 想查看刚刚运行的各个reduceTask时间: 使用jobHistory

在这里插入图片描述

点击对应需要查看的任务:

在这里插入图片描述

点击reduce进入:

在这里插入图片描述

  • 18
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
数据仓库(Data Warehouse)简称DW或DWH,是数据库的一种概念上的升级,可以说是为满足新需求设计的一种新数据库,而这个数据库是需容纳更多的数据,更加庞大的数据集,从逻辑上讲数据仓库和数据库是没有什么区别的。为企业所有级别的决策制定过程,提供所有类型数据支撑的战略集合,主要是用于数据挖掘和数据分析,以建立数据沙盘为基础,为消灭消息孤岛和支持决策为目的而创建的。 数据仓库的应用 1.数据分析、数据挖掘、人工智能、机器学习、风险控制、无人驾驶。 2.数据化运营、精准运营。 3.广告精准、智能投放。 随着我们从IT时代步入DT时代,数据积累量也与日俱增,同时伴随着互联网的发展,越来越多的应用场景产生,传统的数据处理、存储方式已经不能满足日益增长的需求。而互联网行业相比传统行业对新生事物的接受度更高、应用场景更复杂, 因此基于大数据构建的数据仓库先在互联网行业得到了尝试。 高性能高扩展的亿级电商全端实时数据仓库全实现(PC、移动、小程序) ,以热门的互联网电商实际业务应用场景为案例讲解,对电商数据仓库的常见实战指标以及难点实战指标进行了详尽讲解,具体指标包括:每日、月大盘收入报表、高付费用户分析报表、流量域多方位分析、营销域多方位分析、实时排行榜指标分析、用户主题分析、店铺主题时间区间分析等,数据分析涵盖全端(PC、移动、小程序)应用,与互联网企业大数据技术同步,让大家能够真正学到大数据企业级数据仓库的实战经验。本课程凝聚讲师多年一线大数据企业实际项目经验,大数据企业在职架构师亲自授课,全程实操代码,带你体验真实的大数据开发过程,代码现场调试。通过本课程的学习再加上老师的答疑,你完全可以将本案例直接应用于企业。本套课程可以满足世面上绝大多数大数据企业级的数据仓库业务场景,全部代码可以直接部署企业,支撑亿级并发数据分析。该项目代码也是具有极高的商业价值的,大家可以根据自己的业务进行修改,便可以使用。本课程包含的技术:  开发工具为:IDEA、WebStorm Flink1.9.0 Greenplum5.0.0 Hadoop2.6.0 Hbase1.0.0 Kafka2.1.0 Hive1.1.0 HDFS、MapReduce Redis、Flume Sqoop、Zookeeper MyBatis、EhCache SpringBoot2.0.2.RELEASE SpringCloud Finchley.RELEASE Binlog、Canal MySQL、MyCat Vue.js、Nodejs Highcharts课程亮点: 1.与企业对接、真实工业界产品  2.支持海量数据的分析 3.支持全端实时数据分析 4.通用数据仓库分层解决方案 5.数据库实时同步解决方案 6.主流微服务后端系统 7.电商数据仓库实战指标 8.实时加离线多方位分析 9.互联网大数据企业热门技术栈 10.分布式数据库存储解决方案 11.涵盖主流前端技术VUE+jQuery+Ajax+NodeJS 12.大数据热门技术Flink新版本13.集成SpringCloud实现统一整合方案 14.全程代码实操,提供全部代码和资料 15.提供答疑和提供企业技术方案咨询企业一线架构师讲授,代码企业直接复用,提供企业解决方案。  版权归作者所有,盗版将进行法律维权。 

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT界的追风者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值