手把手教你解决 Hive 的数据倾斜

news2025/3/18 19:17:27

文章目录

    • 数据倾斜是什么?
    • 产生数据倾斜的场景
      • 1.空值引发的数据倾斜
      • 2.不可拆分的大文件产生的数据倾斜
      • 3.数值膨胀引发的数据倾斜
      • 4.不同数据类型引发的数据倾斜
      • 5.Count(distinct) 引发的数据倾斜
      • 6.表 Join 操作时引发数据倾斜
      • 7.group by 引发的数据倾斜
    • 解决数据倾斜
      • 数据准备
      • 模拟数据倾斜场景
        • 1.Group By 引发的数据倾斜
        • 2.Count(distinct) 引发的数据倾斜
        • 3.Join 操作引发的数据倾斜

数据倾斜是什么?

在 Hive 中,数据倾斜是指某些任务的数据量或处理时间远远超过其他任务,导致整体任务执行效率低下的现象。

产生数据倾斜的根本原因是在进行 Shuffle 流程后,导致 Key 的分布不均匀,造成某些 Reduce 处理的数量较大,形成数据倾斜,导致整个任务的执行效率下降。

产生数据倾斜的场景

1.空值引发的数据倾斜

如果在进行聚合操作时,存在大量空值,会导致这些空值会被分配到一个 Reduce 中,导致该 Reduce 需要处理大量的数据,造成数据倾斜现象。

解决方法

  • 过滤空值

  • 给空值数据设计随机值

例如:

select a,b,c from t1 join t2 on case when t1.id is null then concat('randNum',rand()) else t1.id end = t2.id;

2.不可拆分的大文件产生的数据倾斜

在处理某些大文件数据时,由于其源压缩格式不能进行拆分,例如:Gzip、Snappy,导致在处理这些数据时,只能将其放在一个 MapTask 中进行处理,从而产生数据倾斜。

解决方法

  • 先在 HDFS 上进行解压,然后再进行操作

  • 尽量选用可拆分的压缩文件格式

3.数值膨胀引发的数据倾斜

在多维聚合计算时,如果进行分组聚合的字段过多,且数据量很大,Map 端的聚合不能很好地起到数据压缩的情况下,会导致 Map 端产出的数据急速膨胀,导致作业产生 OOM。

解决方法

  • 在 Hive 中可以通过参数 hive.new.job.grouping.set.cardinality 配置的方式自动控制作业的拆解,该参数默认值是 30。该参数主要针对 grouping sets/rollups/cubes 这类多维聚合的操作生效,如果最后拆解的键组合大于该值,会启用新的任务去处理大于该值之外的组合。如果在处理数据时,某个分组聚合的列有较大的倾斜,可以适当调小该值。

4.不同数据类型引发的数据倾斜

表 A 的 Key 值是 int 类型,表 B 中的 Key 值既有 int 又有 string 类型,在两个表之间进行 Join 操作时,会默认按 Hash 中 int 类型的 id 进行分配,导致大量 string 类型的数据会被分配到一个 Reduce 中,产生数据倾斜。

解决方法

  • 在连接时转换为统一的数据类型,将表 B 中的 Key 统一转换为 string 类型(虽然表 A 的 Key 是 int 类型,但是 Hive 底层会在连接时会进行隐式转换)

  • 在建表时,统一数据类型

5.Count(distinct) 引发的数据倾斜

Count(distinct) 是产生数据倾斜的经典场景,因为该任务是全局排序的操作,在没有分组的情况下,只会产生一个 Reduce 任务,数据量大时自然就会产生数据倾斜。

解决方法

  • 先进行去重操作,然后分组统计

例如:

-- 优化前
select a,count(distinct b) from t group by a;

-- 优化后
select a,sum(1) from (select a, b from t group by a,b)t1 group by a;

如果去重字段较多,可以先采用上述方式进行计算,最后再进行 union all

6.表 Join 操作时引发数据倾斜

在小表 Join 大表时,如果某个 Key 的值过大,就会产生数据倾斜。

解决方法

  • MapJoin,将小表加载到内存中,在 Map 端就进行 Join 操作,避免了 Shuffle 流程。在 Hive 中默认开启该功能,但限制了小表的大小,可以通过配置参数 set hive.mapjoin.smalltable.filesize=2500000; 进行修改,默认小表最大 25MB。将小表放在 Join 操作中的左表中,优先加载到内存中。

  • set hive.auto.convert.join=true; 设置是否允许 Hive 自动根据文件量大小将 common join 转成 map join,避免大量的 Shuffle 操作,该值默认为 true

MapJoin 优化就是在 Map 阶段完成 Join 工作,而不是像通常的 common join 在 Reduce 阶段按照 Join 的列值进行分发数据到每个 Reduce 上进行 Join 工作,这样避免了 Shuffle 阶段,从而避免了数据倾斜。

这个操作会将所有的小表全量复制到每个 Map 任务节点,然后再将小表缓存在每个 Map 节点的内存里与大表进行 Join 工作,所以小表的大小的不能太大,否则会出现 OOM 报错。

在 Hive 中,还可以通过 hive.optimize.skewjoin 参数用于处理在执行 JOIN 操作时可能出现的数据倾斜问题,默认为 false。设置这个参数为 true可以让 Hive 自动优化和处理倾斜的 JOIN,从而提高查询性能。

对于检测到的倾斜键值,Hive 会将其单独处理。具体方法是将这些倾斜数据分成小批次,并分配给多个 Reducer 处理。在 Map 阶段,Hive 会统计每个键值的数据量,如果某个键值的数据量超过一定阈值(该值可以通过参数 hive.skewjoin.key 调整,默认为 100000 行),则会被判定为倾斜数据。

如果是大表 Join 大表的场景,且数据量无法通过过滤等操作减少,那么这种情况就只能调整 Reduce 的大小了。

7.group by 引发的数据倾斜

分组维度过小,某值的数量过多,从而引发数据倾斜。

解决方法

  • 调整 Hive 参数
set hive.map.aggr=true; --默认true,在map端会做部分聚集操作,效率更高但需要更多的内存
-- 进行GroupBy操作时,是否自动检测并处理数据倾斜,均衡Reducer负载,默认为false
set hive.groupby.skewindata=true;

hive.groupby.skewindata 设置为 true 时,它会使数据倾斜时达到负载均衡。

它将计算变成了两个 MapReduce,在第一个 MR 的 shuffle 过程进行 Partition 时,随机给 key 打标记,使每个 key 随机均匀分布到各个 Reduce 上计算,但是这样只能完成部分计算,因为相同 key 没有分配到相同 Reduce上。

第二个 MR 就是正常的执行流程,对第一次 MR 的执行结果再次执行,但是数据分布不均匀的问题在第一个 MR 已经得到了很大的改善,所以并不会造成数据倾斜。

解决数据倾斜

数据准备

在这里,我通过 Python 生成了包含数据倾斜问题的模拟数据:

import random

# 文件名
filename = 'input_data.txt'

# 数据量
num_records = 50000000

# 倾斜key
skewed_key = 'key_skewed'

# 生成数据
with open(filename, 'w') as f:
    for _ in range(num_records):
        if random.random() < 0.8:
            f.write(f'{skewed_key}\t{random.randint(1, 100)}\n')
        else:
            key = f'key_{random.randint(1, 10000)}'
            value = random.randint(1, 100)
            f.write(f'{key}\t{value}\n')

print(f'Data written to {filename}')

一共会生成 5000w 条数据,其中 80% 为倾斜数据,因为它们的 key 相同,剩下的为正常数据。

数据生成完成后,大小约为 643MB,将生成的数据上传到 HDFS 中:

hdfs dfs -mkdir -p /user/hive/warehouse/skew_data
hdfs dfs -put input_data.txt /user/hive/warehouse/skew_data/

接下来,创建 Hive 表并加载数据:

CREATE DATABASE IF NOT EXISTS skew_db;
USE skew_db;

CREATE TABLE IF NOT EXISTS skewed_table (
    key STRING,
    value INT
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';

LOAD DATA INPATH '/user/hive/warehouse/skew_data/input_data.txt' INTO TABLE skewed_table;

这里直接创建,不指定任何存储与压缩格式。

模拟数据倾斜场景

环境说明

  • 执行环境:Hive On Spark
  • YARN 总资源:<memory:12 GB, vCores:12>
  • AM 最小资源:<memory:1024, vCores:1>
  • AM 最大资源:<memory:2048, vCores:2>
  • 容量调度器:0.8
1.Group By 引发的数据倾斜

在这里,我先不做任何优化操作,直接进行 group by 操作,按 key 分组统计 value 列的累加求和值。

SELECT key, SUM(value)
FROM skewed_table
GROUP BY key;

执行计划如下:

Explain
STAGE DEPENDENCIES:
  Stage-1 is a root stage
  Stage-0 depends on stages: Stage-1

STAGE PLANS:
  Stage: Stage-1
    Spark
      Edges:
        Reducer 2 <- Map 1 (GROUP, 53)
      DagName: ds_20240524105012_45af3c14-bde8-460d-bf4d-ad47b929e96b:1
      Vertices:
        Map 1 
            Map Operator Tree:
                TableScan
                  alias: skewed_table
                  Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                  Select Operator
                    expressions: key (type: string), value (type: int)
                    outputColumnNames: key, value
                    Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                    Group By Operator
                      aggregations: sum(value)
                      keys: key (type: string)
                      mode: hash
                      outputColumnNames: _col0, _col1
                      Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                      Reduce Output Operator
                        key expressions: _col0 (type: string)
                        sort order: +
                        Map-reduce partition columns: _col0 (type: string)
                        Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                        value expressions: _col1 (type: bigint)
            Execution mode: vectorized
        Reducer 2 
            Execution mode: vectorized
            Reduce Operator Tree:
              Group By Operator
                aggregations: sum(VALUE._col0)
                keys: KEY._col0 (type: string)
                mode: mergepartial
                outputColumnNames: _col0, _col1
                Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                File Output Operator
                  compressed: false
                  Statistics: Num rows: 1 Data size: 6748992000 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

  Stage: Stage-0
    Fetch Operator
      limit: -1
      Processor Tree:
        ListSink

首先,Stage-1 进行表扫描、选择和分组操作,通过 Map 任务将数据分组,然后通过 Reduce 任务聚合数据。接着,Stage-0Stage-1 获取数据,并输出结果。整个过程采用矢量化执行模式以提高性能。

矢量化执行(Vectorized Execution)是一种提高查询性能的技术,通过一次处理一大块数据(数据块或向量),而不是一行一行地处理。其主要优点包括:

  1. 更高的处理速度:利用现代 CPU 的并行处理能力,对一批数据进行同时操作。
  2. 减少函数调用:在处理一大块数据时,只需要一次函数调用,而不是每行数据都调用一次。
  3. 更好的缓存利用:处理连续的大块数据,提高 CPU 缓存的利用效率。
  4. 优化内存访问:更高效的内存读取模式,减少访问延迟。
    在 Hive 中,可以通过启用矢量化执行参数来利用这种技术:
SET hive.vectorized.execution.enabled = true;
SET hive.vectorized.execution.reduce.enabled = true;

这样,Hive 在处理查询时,会使用矢量化执行来加速数据处理,特别是在处理大数据量时效果显著。

未优化前执行过程如下:

在这里插入图片描述

总运行时长为 23s,其中有 3 MapTask, 53 个 ReduceTask,即使没有进行优化,但得益于 Spark 优秀的计算与自动优化能力,它也能做到高效率的运行。

下面调整 Hive 参数,对 group by 数据倾斜进行优化:

-- 控制是否在Map阶段进行部分聚合,默认为true
set hive.map.aggr=true;
-- 进行GroupBy操作时,是否自动检测并处理数据倾斜,均衡Reducer负载,默认为false
set hive.groupby.skewindata=true;

优化后的执行计划如下:

Explain
STAGE DEPENDENCIES:
  Stage-1 is a root stage
  Stage-0 depends on stages: Stage-1

STAGE PLANS:
  Stage: Stage-1
    Spark
      Edges:
        Reducer 2 <- Map 1 (GROUP PARTITION-LEVEL SORT, 53)
        Reducer 3 <- Reducer 2 (GROUP, 53)
      DagName: ds_20240524111335_c1a08cdc-0745-4ee7-8bcb-73813337e5ba:5
      Vertices:
        Map 1 
            Map Operator Tree:
                TableScan
                  alias: skewed_table
                  Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                  Select Operator
                    expressions: key (type: string), value (type: int)
                    outputColumnNames: key, value
                    Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                    Group By Operator
                      aggregations: sum(value)
                      keys: key (type: string)
                      mode: hash
                      outputColumnNames: _col0, _col1
                      Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                      Reduce Output Operator
                        key expressions: _col0 (type: string)
                        sort order: +
                        Map-reduce partition columns: rand() (type: double)
                        Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                        value expressions: _col1 (type: bigint)
            Execution mode: vectorized
        Reducer 2 
            Execution mode: vectorized
            Reduce Operator Tree:
              Group By Operator
                aggregations: sum(VALUE._col0)
                keys: KEY._col0 (type: string)
                mode: partials
                outputColumnNames: _col0, _col1
                Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                Reduce Output Operator
                  key expressions: _col0 (type: string)
                  sort order: +
                  Map-reduce partition columns: _col0 (type: string)
                  Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                  value expressions: _col1 (type: bigint)
        Reducer 3 
            Execution mode: vectorized
            Reduce Operator Tree:
              Group By Operator
                aggregations: sum(VALUE._col0)
                keys: KEY._col0 (type: string)
                mode: final
                outputColumnNames: _col0, _col1
                Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                File Output Operator
                  compressed: false
                  Statistics: Num rows: 1 Data size: 6748992000 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

  Stage: Stage-0
    Fetch Operator
      limit: -1
      Processor Tree:
        ListSink

和上面一样,Stage-1 进行表扫描、选择和分组操作,通过 Map 任务将数据分组。第一个 Reduce 做部分聚合(mode: partials),第二个 Reduce 完成最终聚合(mode: final)。接着,Stage-0Stage-1 获取数据,并输出结果。同样,整个过程采用矢量化执行模式。

优化后执行过程如下:

在这里插入图片描述
我们从 DAG 图中可以看出,它多了一个阶段,作用是保障倾斜 key 进行分组时的负载均衡操作,改善倾斜 key 造成的影响。

其中有 3 MapTask,2 个 Reduce 任务,每次均为 53 个 ReduceTask。虽然增加了 Reduce 任务,但是运行时长缩短到了 15s,优化了整整 8s,可以看到调参还是起到了一定的作用。

如果你使用的引擎是 Hive On MR,那么该效果会体现的更加明显,感兴趣的同学可以自行尝试一下。

2.Count(distinct) 引发的数据倾斜

不做任何优化,按 key 分组统计每组中存在多少个不同的 value

SELECT key,count(distinct value) FROM skewed_table GROUP BY key;

执行计划如下:

Explain
STAGE DEPENDENCIES:
  Stage-1 is a root stage
  Stage-0 depends on stages: Stage-1

STAGE PLANS:
  Stage: Stage-1
    Spark
      Edges:
        Reducer 2 <- Map 1 (GROUP PARTITION-LEVEL SORT, 53)
      DagName: ds_20240524143342_8247aea2-8786-4f99-a4a8-79cfd844b80a:11
      Vertices:
        Map 1 
            Map Operator Tree:
                TableScan
                  alias: skewed_table
                  Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                  Select Operator
                    expressions: key (type: string), value (type: int)
                    outputColumnNames: key, value
                    Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                    Group By Operator
                      keys: key (type: string), value (type: int)
                      mode: hash
                      outputColumnNames: _col0, _col1
                      Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                      Reduce Output Operator
                        key expressions: _col0 (type: string), _col1 (type: int)
                        sort order: ++
                        Map-reduce partition columns: _col0 (type: string)
                        Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
            Execution mode: vectorized
        Reducer 2 
            Execution mode: vectorized
            Reduce Operator Tree:
              Group By Operator
                keys: KEY._col0 (type: string), KEY._col1 (type: int)
                mode: mergepartial
                outputColumnNames: _col0, _col1
                Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                Group By Operator
                  aggregations: count(_col1)
                  keys: _col0 (type: string)
                  mode: complete
                  outputColumnNames: _col0, _col1
                  Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                  File Output Operator
                    compressed: false
                    Statistics: Num rows: 1 Data size: 6748992000 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

  Stage: Stage-0
    Fetch Operator
      limit: -1
      Processor Tree:
        ListSink

首先,Stage-1 进行表扫描、选择和分组操作,通过 Map 任务将数据分组。

这里在 Reduce 任务中,一共有两次 GroupBy 操作,第一次根据 keyvalue 列联合分组去重,减少数据量,然后第二次根据 key 分组统计。最后,Stage-0Stage-1 获取数据,并输出结果,整个过程采用矢量化执行模式。

其实,从这里可以看出,Spark 自动对这种情况进行了优化,它采用的这种方式和我们手动调优的思路是一样的。

未优化前执行过程如下:

在这里插入图片描述

共耗时 25s

下面通过对 SQL 语句进行优化:

SELECT key,sum(1) FROM (SELECT key,value FROM skewed_table GROUP BY key,value)t1 GROUP BY key;

手动优化后的执行计划如下:

Explain
STAGE DEPENDENCIES:
  Stage-1 is a root stage
  Stage-0 depends on stages: Stage-1

STAGE PLANS:
  Stage: Stage-1
    Spark
      Edges:
        Reducer 2 <- Map 1 (GROUP PARTITION-LEVEL SORT, 53)
      DagName: ds_20240524163733_b1dc11cb-2d4b-4a59-8074-804ac1c5a503:13
      Vertices:
        Map 1 
            Map Operator Tree:
                TableScan
                  alias: skewed_table
                  Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                  Select Operator
                    expressions: key (type: string), value (type: int)
                    outputColumnNames: key, value
                    Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                    Group By Operator
                      keys: key (type: string), value (type: int)
                      mode: hash
                      outputColumnNames: _col0, _col1
                      Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                      Reduce Output Operator
                        key expressions: _col0 (type: string), _col1 (type: int)
                        sort order: ++
                        Map-reduce partition columns: _col0 (type: string)
                        Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
            Execution mode: vectorized
        Reducer 2 
            Execution mode: vectorized
            Reduce Operator Tree:
              Group By Operator
                keys: KEY._col0 (type: string), KEY._col1 (type: int)
                mode: mergepartial
                outputColumnNames: _col0, _col1
                Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                Select Operator
                  expressions: _col0 (type: string)
                  outputColumnNames: _col0
                  Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                  Group By Operator
                    aggregations: sum(1)
                    keys: _col0 (type: string)
                    mode: complete
                    outputColumnNames: _col0, _col1
                    Statistics: Num rows: 1 Data size: 6748992000 Basic stats: COMPLETE Column stats: NONE
                    File Output Operator
                      compressed: false
                      Statistics: Num rows: 1 Data size: 6748992000 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

  Stage: Stage-0
    Fetch Operator
      limit: -1
      Processor Tree:
        ListSink

优化后执行过程如下:

在这里插入图片描述

总耗时 20s,缩短了 5s,从执行计划中可以看出,优化前和优化前差不多,这完全是因为 Spark 的功劳,因为它对许多场景都进行了优化,大大减轻了开发人员的负担。

这里快 5s 是因为省去了 Spark 自动调优的时间,因为对 SQL 进行了手动调优,所以 Spark 发现无需再进行优化,直接运行即可,所以这里快了 5s

3.Join 操作引发的数据倾斜

为了模拟 Join 操作,这里根据主表的数据,再重新创建一张表(后续将此表称为小表):

CREATE TABLE small_table AS SELECT key,'1' `value` FROM skewed_table GROUP BY key;

小表中一共有 10001 条记录,其中的 key 都是不同的值。

现在,将两个表根据 key 进行 Join,完成联合查询:

SELECT
  smt.key,smt.value,skt.key,skt.value
FROM
  small_table smt
JOIN
  skewed_table skt
ON
  skt.key = smt.key
LIMIT
	10;

毫无疑问,这里肯定会引发数据倾斜,我们小表里头的数据是根据主表的 keyvalue 联合去重后插入的,但是由于我们的主表中,某个 key 存在大量的数据(这里该 key 约为 4000w 条),所以当我在执行 Join 操作时,会因为该 key 直接引发数据膨胀,产生严重的数据倾斜。

先来看看执行流程:

在这里插入图片描述

在这个案例中,一共有两个 Map 任务,但是没有 Reduce 任务,这是因为什么呢?

先来看看它们详细的执行内容,首先看第一个 Map:

在这里插入图片描述

第一个 Map 读取的是小表 small_table 中的数据。

现在我们再来看看第二个 Map 任务:

在这里插入图片描述

第二个 Map 读取的是主表 skewed_table 中的数据,一共有 3 个 MapTask 任务,因为我们主表的数据文件一共有约 643MB,一个 MapTask 处理 256MB,所以这里需要 3 个 MapTask。

之所以没有 Reduce 任务是因为自动转为了 MapJoin 操作,因为我们小表内容比较少,数据量才 1w 条(约 10MB),而主表有 5000w 条(约 643MB),满足转换为 MapJoin 的条件,它会提前将小表加载到内存中,然后在 Map 阶段执行 Join 操作,避免了 Shuffle 阶段。

所以即使我这里某个 key 的值达到了 4000w 条,它也不会发生数据倾斜。

MapJoin 是默认开启的,所以这里会自动进行转换,可以通过如下参数进行调整:

-- 是否将common join转成map join,默认为true;
set hive.auto.convert.join=true;
--大表Join小表判断的阈值,如果表的大小小于25Mb,则会被判定为小表,默认小表大小为:25Mb
set hive.mapjoin.smalltable.filesize=25000000;

还可以进行一些其它的优化操作:

-- 是否自动处理倾斜的键值,默认false
set hive.optimize.skewjoin=true;
-- 处理自动倾斜的阈值,默认10w行
set hive.skewjoin.key=100000;

当我们开启 Skew Join 之后,在运行时,会对数据进行扫描并检测哪个 key 会出现倾斜,对于会倾斜的 key,会将其分散到多个 Reducer 处理,从而均衡负载,提高查询性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1694441.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是SSL证书?如何选择SSL证书?

在浏览网站的时候&#xff0c;你会不会有这样一些疑问。 为什么有的网站是http://开头&#xff0c;有的却是https://&#xff1f;它们有什么区别吗&#xff1f; 经常访问的网站&#xff0c;浏览器突然提示“安全证书过期”&#xff0c;提醒你不要浏览该网址&#xff1f; 这一切…

推荐一款自助分析的财务分析软件:奥威BI软件

奥威BI软件是一款支持多维度动态自助分析的软件&#xff0c;预设了智能财务分析方案&#xff0c;提供内存行列计算模型解决财务指标计算难题&#xff0c;界面简洁&#xff0c;以点击、拖曳操作为主&#xff0c;十分适合没有IT背景的财务人做财务分析。因此也经常有人说奥威BI软…

前后端开发入门全攻略:零基础学起

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、前后端开发概览 二、后端开发基础&#xff1a;Flask框架入门 代码案例&#xff1a;Hel…

驱动执行报“Attribute var: Invalid permissions 0665”

问题&#xff1a;执行驱动的时候会报下面这个错误 WARNING: CPU: 0 PID: 123 at fs/sysfs/group.c:61 internal_create_group0x170/0x264() Attribute var: Invalid permissions 0665 问题分析&#xff1a;查看 fs/sysfs/group.c:61的代码&#xff0c;发现是我设置 module_par…

Filter和Interceptor

会话 cookie 服务器自动将cookie响应给浏览器 浏览器接收响应回来的数据 自动将cookie存储在本地&#xff0c; 后续请求当中浏览器将cookie携带到服务器 cookie不能跨域&#xff0c;存储在客户端 session 存储在服务器 token------>JWT 存储在客户端&#xff0c; 服务…

独享IP是原生IP吗?二者有何区别?

原生IP&#xff1a; 原生IP是指由Internet服务提供商&#xff08;ISP&#xff09;直接分配给用户的IP地址&#xff0c;这些IP地址通常反映了用户的实际地理位置和网络连接。原生IP是用户在其所在地区或国家使用的真实IP地址&#xff0c;与用户的物理位置直接相关。在跨境电商中…

统计信息和AUTO SQL TUNING任务重合引发的Library Cache Lock血案

一、引言 行里的短信平台&#xff0c;在晚上22:00的时候&#xff0c;突然出现卡顿&#xff0c;卡顿持续1分钟左右&#xff0c;这1分钟内&#xff0c;短信超过30秒才发送成功。因此&#xff0c;对数据库层面开展了一些分析&#xff0c;并且发现了些问题。 二、分析过程 1.查看…

从 0 实现一个文件搜索工具 (Java 项目)

背景 各文件系统下, 都有提供文件查找的功能, 但是一般而言搜索速度很慢 本项目仿照 everything 工具, 实现本地文件的快速搜索 实现功能 选择指定本地目录, 根据输入的信息, 进行搜索, 显示指定目录下的匹配文件信息文件夹包含中文时, 支持汉语拼音搜索 (全拼 / 首字母匹配…

CSS伪类实现input聚焦时,上层div样式改变

CSS伪类实现input聚焦时&#xff0c;上层div样式改变 可以使用:focus-within伪类选择器&#xff0c;它会在div内的任何元素获得焦点时选择该div&#xff0c;明确的是&#xff0c;获得焦点和被点击是不相等的&#xff0c;div能被点击&#xff0c;但是不能获得焦点&#xff0c;也…

ViT:1 从DETR说起

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调重新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则提供了大模型领域最新技…

东哥一句兄弟,你还当真了?

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 你还真把自己当刘强东兄弟了?谁跟你是兄弟了?你在国外的房子又不给我住&#xff0c;你出去旅游也不带上我!都成人年了&#xff0c;东哥一句客套话&#xff0c;别当真! 今天&#xff0c;东哥在高管会上直言&…

存储+调优:存储-IP-SAN-EXTENSION

存储调优&#xff1a;存储-IP-SAN-EXTENSION 文件系统的锁标记 GFS&#xff08;锁表空间&#xff09; ----------- ------------ ------------- 节点 | ndoe1 | | node2 | | node3 | ---------- ------…

C++成员函数 - 析构函数

析构函数 析构函数 是特殊的成员函数&#xff0c;其 特征 如下&#xff1a; 1. 析构函数名是在类名前加上字符 ~ 。 2. 无参数无返回值类型。 3. 一个类只能有一个析构函数。若未显式定义&#xff0c;系统会自动生成默认的析构函数。注意&#xff1a;析构函数不能重 载 …

K8S认证|CKA题库+答案| 17. 节点维护

17、节点维护 CKA v1.29.0模拟系统免费下载试用&#xff1a; 百度网盘&#xff1a;https://pan.baidu.com/s/1vVR_AK6MVK2Jrz0n0R2GoQ?pwdwbki 题目&#xff1a; 您必须在以下Cluster/Node上完成此考题&#xff1a; Cluster Ma…

图论(三)(最小生成树)

一、图的表示&#xff08;简要概述&#xff09; 对于图G&#xff08;V&#xff0c;E&#xff09;&#xff08; V 为节点的集合&#xff0c;E 为边的集合 V*V 的子集&#xff09;有两种表示方法&#xff1a;邻接链表和邻接矩阵&#xff0c;两种表示方法既可以表示有向图&#x…

输入输出(3)——C++的标准输入流

目录 一、cin 流 二、成员函数 get 获取一个字符 (一)无参数的get函数。 (二)有一个参数的get函数。 (三&#xff09;有3个参数的get函数 (四&#xff09;用成员函数 getline 函数读取一行字符 (五&#xff09;用成员函数 read 读取一串字符 (六&#xff09;istream 类…

[机缘参悟-187] - 《道家-水木然人间清醒1》读书笔记 - 真相本质 -10- 关系界限 - 一个人只有放下自我,才能看清世界的真相

目录 一、现实生活中&#xff0c;每个人都是盲人摸象 二、一个人认知的本质是神经网络的模型训练 三、每个人的认知具有局限 四、放下自我&#xff0c;就是跳出自我的认知局限 五、站在上帝的视角&#xff0c;俯瞰不同众生的千差万别的大脑认知系统 六、个体的独特性&…

汇编实现的操作系统

掌握X86汇编语言和GDB程序调试工具对于程序员来说是非常重要的_gdb 查看x86汇编-CSDN博客 掌握编译器和虚拟机的开发有哪些方面的好处-CSDN博客 Ville Mikael Turjanmaan开发的一个操作系统MenuetOS可运行在IA-32, x86-64平台上&#xff0c;完全用 64 位汇编语言编写。功能包…

三、ESP32-IDF之LED

实现 ESP32-S3 的 IO 作为输出功能&#xff0c;实现LED灯以500毫秒闪烁一次 1、GPIO&LED简介 1.1、GPIO简介 GPIO 是负责控制或采集外部器件信息的外设&#xff0c;主要负责输入输出功能。 1.2、LED简介 LED&#xff0c;即发光二极管。 2、硬件设计 (1)原理图 LED 接…

模块化程序设计(函数的定义、调用、参数传递、局部变量、全局变量)

函数的引入&#xff1a; 我们曾经学习了程序设计中的三种基本控制结构&#xff08;顺序、分支、循环&#xff09;。用它们可以组成任何程序。但在应用中&#xff0c;还经常用到子程序结构。 通常&#xff0c;在程序设计中&#xff0c;我们会发现一些程序段在程序的不同地方反复…