大数据Hive执行计划详解与优化

Hive 的执行计划比传统数据库更复杂,因为它将 SQL 翻译成多阶段的 MapReduce、Tez 或 Spark 任务。

Hive 提供了两种类型的执行计划,用于不同阶段的优化和分析:

  1. 抽象语法树 (AST):SQL -> 抽象语法树的转换。
  2. 查询执行计划 (Query Execution Plan)这是我们性能调优最关心的部分,它展示了 Hive 如何将查询转换为底层计算框架(如 MR/Tez/Spark)的任务。它又分为两个阶段:
    • Stage 1: Logical Plan (逻辑执行计划):由多个逻辑操作符组成的算子树。
    • Stage 2: Physical Plan (物理执行计划):将逻辑操作符优化、切分后,生成的具体物理执行步骤,最终会转换为 MR/Tez/Spark 的 DAG(有向无环图)。

1. 如何查看执行计划?

主要通过 EXPLAINEXPLAIN EXTENDED 命令来查看。

基础语法:EXPLAIN
EXPLAIN [FORMATTED|EXTENDED|DEPENDENCY|AUTHORIZATION|...] 
your_sql_statement;

最常用的选项是 FORMATTEDEXTENDED

示例:查看一个简单查询的执行计划
-- 先设置显示表头,方便阅读(可选)
set hive.cli.print.header=true;

-- 1. 基础EXPLAIN
EXPLAIN
SELECT deptno, AVG(sal) AS avg_sal
FROM emp
WHERE sal > 1000
GROUP BY deptno
HAVING avg_sal > 2000;

-- 2. 查看更详细的计划(推荐使用)
EXPLAIN FORMATTED
SELECT deptno, AVG(sal) AS avg_sal
FROM emp
WHERE sal > 1000
GROUP BY deptno
HAVING avg_sal > 2000;

-- 3. 查看最最详细的计划(信息量巨大)
EXPLAIN EXTENDED
SELECT deptno, AVG(sal) AS avg_sal
FROM emp
WHERE sal > 1000
GROUP BY deptno
HAVING avg_sal > 2000;

2. 执行计划结果解读(核心)

我们以 EXPLAIN FORMATTED 的输出为例进行解读。输出内容非常结构化,主要包含以下几个部分:

第一部分:STAGE DEPENDENCIES (阶段依赖)

这部分展示了所有执行阶段的依赖关系,即执行的先后顺序。

STAGE DEPENDENCIES:
  Stage-1 is a root stage
  Stage-0 depends on stages: Stage-1
  • 解读:这表示这个查询有两个阶段:Stage-1Stage-0
  • Stage-1 是根阶段,最先执行。
  • Stage-0 是一个后续阶段,它依赖于 Stage-1 的执行结果(通常是做最终的聚合、排序或限制输出)。

这是理解任务并行度和执行流程的第一步。

第二部分:STAGE PLANS (阶段计划)

这是执行计划的核心,详细描述了每个 Stage 要做什么。 我们会看到类似以下的结构:

STAGE PLANS:
  Stage: Stage-1
    Map Reduce
      Map Operator Tree:
          TableScan // 扫描表
            alias: emp
            Statistics: Num rows: 1 Data size: 1000 Basic stats: COMPLETE Column stats: NONE
            Filter Operator // 过滤操作 (对应WHERE子句)
              predicate: (sal > 1000) (type: boolean)
              Statistics: Num rows: 1 Data size: 500 Basic stats: COMPLETE Column stats: NONE
              Select Operator // 选择列操作
                expressions: sal (type: double), deptno (type: int)
                outputColumnNames: sal, deptno
                Statistics: Num rows: 1 Data size: 500 Basic stats: COMPLETE Column stats: NONE
                Group By Operator // 分组聚合操作 (对应GROUP BY)
                  aggregations: avg(sal)
                  keys: deptno (type: int)
                  mode: hash
                  outputColumnNames: _col0, _col1
                  Statistics: Num rows: 1 Data size: 500 Basic stats: COMPLETE Column stats: NONE
                  Reduce Output Operator // Map端的输出,准备发给Reduce
                    key expressions: _col0 (type: int)
                    sort order: +
                    Map-reduce partition columns: _col0 (type: int)
                    Statistics: Num rows: 1 Data size: 500 Basic stats: COMPLETE Column stats: NONE
                    value expressions: _col1 (type: double)
      Reduce Operator Tree:
        Group By Operator // Reduce端的分组聚合
          aggregations: avg(VALUE._col0)
          keys: KEY._col0
          mode: mergepartial
          outputColumnNames: _col0, _col1
          Statistics: Num rows: 1 Data size: 500 Basic stats: COMPLETE Column stats: NONE
          Filter Operator // 过滤操作 (对应HAVING子句)
            predicate: (_col1 > 2000.0) (type: boolean)
            Statistics: Num rows: 1 Data size: 500 Basic stats: COMPLETE Column stats: NONE
            File Output Operator // 输出结果
              compressed: false
              Statistics: Num rows: 1 Data size: 500 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
关键操作符 (Operator) 解读:
操作符 (Operator)描述解读与优化点
TableScan表扫描读取数据源。关注 alias(表名)和 Statistics(统计信息)。
Filter Operator过滤对应 WHEREHAVING 子句。查看 predicate 了解过滤条件。尽早过滤数据能大幅减少后续处理的数据量
Select Operator列投影选择需要输出的列。查看 expressionsoutputColumnNames只选择必要的列,避免 SELECT *
Group By Operator分组聚合对应 GROUP BY。注意 mode
- hash:在 Map 端进行部分聚合,极佳优化。
- mergepartial:在 Reduce 端合并 Map 端的部分聚合结果。
- complete:完全聚合。
Reduce Output OperatorMap 端输出决定 Map 端输出如何分区、排序给 Reduce 端。关注 key expressions(分区/排序键)和 Map-reduce partition columns这关系到数据倾斜
Join Operator表连接(本例未出现)最常见的性能瓶颈。重点关注连接类型和大小表顺序。
File Output Operator结果输出写出最终结果。
Statistics统计信息极其重要! 包含 Num rows(行数)和 Data size(数据大小)的预估。如果显示 Column stats: NONE,说明缺少列统计信息,可能导致优化器生成劣质计划。需运行 ANALYZE TABLE 收集统计信息

3. 核心性能调优关注点

当您查看 Hive 执行计划时,请带着以下问题去分析:

  1. 数据流是否高效?

    • 查看 STAGE DEPENDENCIES,阶段是否过多?能否合并?
    • 警惕 Cartesian Product(笛卡尔积),这通常是性能灾难。
  2. 是否有数据倾斜 (Data Skew) 风险?

    • 查看 Group By OperatorReduce Output Operatorkey。如果某个 key 的值特别多,会导致单个 Reduce 任务处理大量数据,远慢于其他任务。
    • 优化方案:使用 set hive.groupby.skewindata=true; 或手动处理倾斜 key。
  3. 统计信息是否准确?

    • 检查每个 Operator 下的 Statistics。如果一直是 Num rows: 1Data size: xxx,说明优化器在瞎猜,计划很可能不是最优的。
    • 优化方案:对表和相关列收集统计信息:ANALYZE TABLE emp COMPUTE STATISTICS;ANALYZE TABLE emp COMPUTE STATISTICS FOR COLUMNS sal, deptno;
  4. 是否用上了分区和分桶?

    • TableScan 中,如果表有分区,应该能看到分区过滤条件,例如 partition predicate: (month=202405)避免全表扫描
  5. 连接 (JOIN) 操作是否高效?

    • 确保大表在最后(对于旧版 MapReduce Join)或使用 MapJoin(对于小表)。
    • 查看计划中是否有 Map Join Operator,这表示小表被加载到内存中,效率极高。如果没有,可以尝试提示:SELECT /*+ MAPJOIN(small_table) */ ... 或设置 set hive.auto.convert.join=true;

总结

  1. 命令:使用 EXPLAIN FORMATTED 获取最清晰易读的计划。
  2. 步骤:先看 STAGE DEPENDENCIES 了解阶段流程,再深入 STAGE PLANS 分析每个操作符的细节。
  3. 核心:重点关注 Statistics(统计信息)、Filter(过滤时机)、Group BymodeJoin 的类型以及 Reduce Output 的 key(数据倾斜)。
  4. 优化:根据计划反馈的问题,采取相应措施:收集统计信息、避免笛卡尔积、处理数据倾斜、利用分区剪裁、启用 MapJoin 等

熟练阅读 Hive 执行计划是从“会用 Hive”到“精通 Hive 调优”的关键一步。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值