百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

大数据Hive-SQL执行计划解读(explain)

wxin55 2024-11-06 12:44 15 浏览 0 评论

Hive SQL的执行计划描绘SQL实际执行的整体轮廓,通过执行计划能了解SQL程序再转换成相应计算引擎的执行逻辑,掌握了执行逻辑也就好把握程序出现的瓶颈点从而能够实现更有针对性的优化,此外还能帮助开发者识别看似等价的SQL其实不等价,看似不等价的SQL其实是等价的SQL。可以说执行计划是打开SQL优化大门的一把钥匙。

Hive在不同的版本会采用不同的方式生成执行计划。在Hive早期版本中使用基于规则的方式生成执行计划,这种方式会基于既定的规则来生成执行计划,不会根据环境变化选择不同的执行计划。在Hive 0.14版本及以后,Hive集成了Apache Calcite,使得Hive也能够基于成本代价来生成执行计划,这种方式能够结合Hive的元数据信息和Hive运行过程收集的各类统计信息推测一个更为合理的执行计划出来。Hive目前所提供的执行计划都是预估的执行计划。在关系型型数据库,例如Oracle还会提供一种真实的计划,即SQL实际执行完成后,才能获得的执行计划。

通过本章的学习,读者应该能够看懂大部分的HiveSQL的执行计划,并能够理解HiveSQL在执行时每一步的具体操作。

扩展:在Hive 2.0版本以后加大了基于成本优化器(CBO)的支持。

查看SQL的执行计划方式

目前Hive提供的执行计划,可以查看的信息有以下几种:

  • 查看执行计划基本信息,即explain。
  • 查看执行计划的扩展信息,即explain extended。
  • 查看SQL数据输入依赖的信息,即explain dependency。
  • 查看SQL操作相关权限的信息,即explain authorization。
  • 查看SQL的向量化描述信息,即explain vectorization。

explain查看执行计划基本信息

在查询语句的SQL前面加上关键字explain是查看执行计划的基本方法,用explain打开的执行计划包含两部分:

  • l 作业的依赖关系图,即STAGE DEPENDENCIES。
  • l 每个作业的详细信息,即STAGE PLANS。

我们见下面的案例1,来看下基本执行计划包含的内容。

案例1 查看简单SQL的执行计划

--默认情况下,使用MapReduce计算引擎
explain
--下面的SQL表示统计年龄小于30岁的各个年龄段中,名字中带“红”的人数
select s_age,count(1) num from student_tb_orc
where s_age<30 and s_name like '%红%'
group by s_age;

下图是案例1的执行结果的部分内容:

//描述整任务之间stage的依赖关系
STAGE DEPENDENCIES:
  Stage-1 is a root stage
  Stage-0 depends on stages: Stage-1
//每个stage的详细信息
STAGE PLANS:
  //stage-1的MapReduce过程
  Stage: Stage-1
Map Reduce
  //表示Map阶段的操作
      Map Operator Tree:
          TableScan
            alias: student_tb_orc
            Statistics: Num rows: 20000000 Data size: 30427200000 Basic stats: COMPLETE Column stats: NONE
            Filter Operator
              predicate: ((s_age < 30) and (s_name like '%红%')) (type: boolean)
              Statistics: …
              Select Operator
                expressions: s_age (type: bigint)
                outputColumnNames: s_age
                Statistics: …
                Group By Operator
                  aggregations: count(1)
                  keys: s_age (type: bigint)
                  mode: hash
                  outputColumnNames: _col0, _col1
                  Statistics: ….
                  Reduce Output Operator
                    key expressions: _col0 (type: bigint)
                    sort order: +
                    Map-reduce partition columns: _col0 (type: bigint)
                    Statistics:….
                    value expressions: _col1 (type: bigint)
Execution mode: vectorized
//Reduce阶段的操作
      Reduce Operator Tree:
        Group By Operator
          aggregations: count(VALUE._col0)
          keys: KEY._col0 (type: bigint)
          mode: mergepartial
          outputColumnNames: _col0, _col1
          Statistics:…
          File Output Operator
            compressed: false
            Statistics:…
            table:
                input format: org.apache.hadoop.mapred.TextInputFormat
                output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
                serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
  Stage: Stage-0
    Fetch Operator
      limit: -1
      Processor Tree:
        ListSink

可以看到stage dependencies描绘了作业之间的依赖关系,即stage0依赖stage-1的执行结果。stage-0表示客户端的读取stage-1的执行结果,stage-1表示如下SQL,即select * from student_tb_orc where s_age<30 and s_name like ‘%红%’的执行过程。

Stage-1分为两个阶段Map和Reduce阶段,对应的执行计划关键词解读如下:

  • l MapReduce:表示当前任务执行所用的计算引擎是MapReduce。
  • l Map Opertaor Tree:表示当前描述的Map阶段执行的操作信息。
  • l Reduce Opertaor Tree:表示当前秒时的是Reduce阶段的操作信息。

接下来解读上面两个操作数的解读,在解读时会尽量保持原有执行计划打印的缩进来解读。

Map阶段

Map操作树(Map Operator Tree)信息解读如下:

  • l TableScan:表示对关键字alias声明的结果集,这里指代student_tb_orc,进行表扫描操作。
  • l Statistics:表示对当前阶段的统计信息。例如当前处理的数据行和数据量。这两个都是预估值。
  • l Filter Operator:表示在之前操作(TableScan)的结果集之上进行数据的过滤。
  • l predicate:表示filter Operator进行过滤时,所用的谓词,即s_age<30 and s_name like '%红%'。
  • l Select Operator:表示在之前的结果集之上对列进行投影,即筛选列。
  • l expressions:表示在需要投影的列,即筛选的列。
  • l outputColNames:表示输出的列名。
  • l Group By Operator:表示在之前的结果集之上分组聚合。
  • l aggreations:表示分组聚合使用的算法,这里是count(1)。
  • l keys:表示分组的列,在该例子表示的是s_age。
  • l Reduce output Operator:表示当前描述的是对之前结果聚会后的输出信息,这表示Map端聚合后的输出信息。
  • l key expressions/value expressions:MapReduce计算引擎,在Map阶段和Reduc阶段输出的都是键值对的形式,这里key expression,value expressions分别描述的就是Map阶段输出的键(key)和输出的值(value)所用的数据列,这里的例子key expressions指代的就是s_age列,value exporess 指代的就是count(1)列。
  • l sort order:表示输出是否进行排序,+表示正序,-表示倒叙。
  • l Map-reduce partition columns:表示Map阶段输出到Reduce阶段的分区列,在Hive-SQL中,可以用distribute by指代分区的列。

Reduce阶段

所涉及的关键词与Map阶段的关键词一样的,字段表示含义相同,不再罗列,下面是Reduce中出现但是在Map阶段没有出现的关键词:

  • l compressed:在File Output Operator中这个关键表示文件输出的结果是否进行压缩,false表示不进行输出压缩。
  • l table:表示当前操作表的信息。
  • l input format/out putformat 分别表示文件输入和输出的文件类型。
  • l serde:表示读取表数据的序列化和反序列化的方式。

在不同计算引擎整个执行计划差别也不大,例如我们可以用下面的案例2得到的执行计划结果,同案例结果对比一下,案例2是将案例1的代码放到Spark引擎上执行。

案例2 在Spark计算引擎上生成的Hive执行计划

-使用spark做为计算引擎,业务逻辑同案例1
set hive.execution.engine=spark;
explain
select s_age,count(1) num from student_tb_orc
where s_age<30 and s_name like '%红%'
group by s_age;

上面命令打印的执行计划如下:

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, 152)
      DagName: hdfs_20190420145757_ef458316-083a-4713-8894-0bd8f06649a9:1
      Vertices:
        Map 1
            Map Operator Tree:
                TableScan
                  alias: student_tb_orc
                  Statistics: Num rows: 20000000 Data size: 30427200000 Basic stats: COMPLETE Column stats: NONE
                  Filter Operator
                    predicate: ((s_age < 30) and (s_name like '%红%')) (type: boolean)
                    Statistics: Num rows: 3333333 Data size: 5071199492 Basic stats: COMPLETE Column stats: NONE
                    Select Operator
                      expressions: s_age (type: bigint)
                      outputColumnNames: s_age
                      Statistics: Num rows: 3333333 Data size: 5071199492 Basic stats: COMPLETE Column stats: NONE
                      Group By Operator
                        aggregations: count(1)
                        keys: s_age (type: bigint)
                        mode: hash
                        outputColumnNames: _col0, _col1
                        Statistics: Num rows: 3333333 Data size: 5071199492 Basic stats: COMPLETE Column stats: NONE
                        Reduce Output Operator
                          key expressions: _col0 (type: bigint)
                          sort order: +
                          Map-reduce partition columns: _col0 (type: bigint)
                          Statistics: Num rows: 3333333 Data size: 5071199492 Basic stats: COMPLETE Column stats: NONE
                          value expressions: _col1 (type: bigint)
            Execution mode: vectorized
        Reducer 2
            Reduce Operator Tree:
              Group By Operator
                aggregations: count(VALUE._col0)
                keys: KEY._col0 (type: bigint)
                mode: mergepartial
                outputColumnNames: _col0, _col1
                Statistics: Num rows: 1666666 Data size: 2535598985 Basic stats: COMPLETE Column stats: NONE
                File Output Operator
                  compressed: false
                  Statistics: Num rows: 1666666 Data size: 2535598985 Basic stats: COMPLETE Column stats: NONE
                  table:
                      input format: org.apache.hadoop.mapred.TextInputFormat
                      output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
                      serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
  Stage: Stage-0
    Fetch Operator
      limit: -1
      Processor Tree:
        ListSink

对比MapReduce最终执行计划,可以发现整体逻辑一致,只是Spark会将所有的任务组织成DAG(有向无环图),所有的任务以顶点表示,任务之间的关系以边表示。

在MapReduce中的Map和Reduce任务在Spark中以Map 1顶点表示,Reducer 2顶点表示,Edges表示顶点之间的联系。从这里我们也再次感受到学会看懂MapReduce的执行计划,对学会看懂其它计算引擎的执行计划也是有极大的帮助。


#Hive##大数据#  #SQL#

相关推荐

ES6中 Promise的使用场景?(es6promise用法例子)

一、介绍Promise,译为承诺,是异步编程的一种解决方案,比传统的解决方案(回调函数)更加合理和更加强大在以往我们如果处理多层异步操作,我们往往会像下面那样编写我们的代码doSomething(f...

JavaScript 对 Promise 并发的处理方法

Promise对象代表一个未来的值,它有三种状态:pending待定,这是Promise的初始状态,它可能成功,也可能失败,前途未卜fulfilled已完成,这是一种成功的状态,此时可以获取...

Promise的九大方法(promise的实例方法)

1、promise.resolv静态方法Promise.resolve(value)可以认为是newPromise方法的语法糖,比如Promise.resolve(42)可以认为是以下代码的语...

360前端一面~面试题解析(360前端开发面试题)

1.组件库按需加载怎么做的,具体打包配了什么-按需加载实现:借助打包工具(如Webpack的require.context或ES模块动态导入),在使用组件时才引入对应的代码。例如在V...

前端面试-Promise 的 finally 怎么实现的?如何在工作中使用?

Promise的finally方法是一个非常有用的工具,它无论Promise是成功(fulfilled)还是失败(rejected)都会执行,且不改变Promise的最终结果。它的实现原...

最简单手写Promise,30行代码理解Promise核心原理和发布订阅模式

看了全网手写Promise的,大部分对于新手还是比较难理解的,其中几个比较难的点:状态还未改变时通过发布订阅模式去收集事件实例化的时候通过调用构造函数里传出来的方法去修改类里面的状态,这个叫Re...

前端分享-Promise可以中途取消啦(promise可以取消吗)

传统Promise就像一台需要手动组装的设备,每次使用都要重新接线。而Promise.withResolvers的出现,相当于给开发者发了一个智能遥控器,可以随时随地控制异步操作。它解决了三大...

手写 Promise(手写输入法 中文)

前言都2020年了,Promise大家肯定都在用了,但是估计很多人对其原理还是一知半解,今天就让我们一起实现一个符合PromiseA+规范的Promise。附PromiseA+规范地址...

什么是 Promise.allSettled()!新手老手都要会?

Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的pr...

前端面试-关于Promise解析与高频面试题示范

Promise是啥,直接上图:Promise就是处理异步函数的API,它可以包裹一个异步函数,在异步函数完成时抛出完成状态,让代码结束远古时无限回掉的窘境。配合async/await语法糖,可...

宇宙厂:为什么前端离不开 Promise.withResolvers() ?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发。1.为什么需要Promise.with...

Promise 新增了一个超实用的 API!

在JavaScript的世界里,Promise一直是处理异步操作的神器。而现在,随着ES2025的发布,Promise又迎来了一个超实用的新成员——Promise.try()!这个新方法简...

一次搞懂 Promise 异步处理(promise 异步顺序执行)

PromisePromise就像这个词的表面意识一样,表示一种承诺、许诺,会在后面给出一个结果,成功或者失败。现在已经成为了主流的异步编程的操作方式,写进了标准里面。状态Promise有且仅有...

Promise 核心机制详解(promise机制的实现原理)

一、Promise的核心状态机Promise本质上是一个状态机,其行为由内部状态严格管控。每个Promise实例在创建时处于Pending(等待)状态,此时异步操作尚未完成。当异步操作成功...

javascript——Promise(js实现promise)

1.PromiseES6开始支持,Promise对象用于一个异步操作的最终完成(包括成功和失败)及结果值的表示。简单说就是处理异步请求的。之所以叫Promise,就是我承诺,如果成功则怎么处理,失败怎...

取消回复欢迎 发表评论: