Hive调优——explain执行计划

一、explain查询计划概述

       explain将Hive SQL 语句的实现步骤、依赖关系进行解析,帮助用户理解一条HQL 语句在底层是如何实现数据的查询及处理,通过分析执行计划来达到Hive 调优,数据倾斜排查等目的。

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Explainicon-default.png?t=N7T8https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Explain

     explain查询计划有三部分:

  • 抽象语法树(AST):Hive使用Antlr解析生成器,可以自动地将HQL生成为抽象语法树
  • stage dependencies:各个stage之间的依赖性
  • stage plan:各个stage的执行计划(物理执行计划)

二、explain实战

     explain执行计划一般分为【仅有Map阶段类型】、【Map+Reduce类型】

2.1 案例一:Map+Reduce类型

数据准备

create table follow
(
  user_id int,
  follower_id int
)row format delimited
fields terminated by '\t';

insert overwrite table follow
values (1,2),
       (1,4),
       (1,5);


create table music_likes
(
  user_id int,
  music_id int
)row format delimited
fields terminated by '\t';

insert overwrite table music_likes 
values (1,20),
       (1,30),
       (1,40),
       (2,10),
       (2,20),
       (2,30),
       (4,10),
       (4,20),
       (4,30),
       (4,60);

执行计划分析

执行如下sql语句:

explain formatted
select
    count(t0.user_id) as cnt
  , sum(t1.music_id)  as sum_f
from follow t0
  left join music_likes t1
      on t0.user_id = t1.user_id
where t0.follower_id > 2
group by t0.follower_id
having cnt > 2
order by sum_f
limit 1;

生成物理执行计划:

STAGE DEPENDENCIES: --//作业依赖关系
  Stage-2 is a root stage
  Stage-1 depends on stages: Stage-2
  Stage-0 depends on stages: Stage-1

STAGE PLANS: --//作业详细信息
  Stage: Stage-2  --//Stage-2 详细任务
    Spark --//表示当前引擎使用的是 Spark
      DagName: atguigu_20240212112407_cb09efe6-ac6e-4a57-a3a8-1b83b2fbf3a7:24
      Vertices:
        Map 4  
            Map Operator Tree:  --//Stage-2 的Map阶段操作信息
                TableScan   --// 扫描表t1
                  alias: t1
                  Statistics: Num rows: 10 Data size: 40 Basic stats: COMPLETE Column stats: NONE  --// 对当前阶段的统计信息,如当前处理的行和数据量(都是预估值)
                  Spark HashTable Sink Operator
                    keys:
                      0 user_id (type: int)
                      1 user_id (type: int)
            Execution mode: vectorized
            Local Work:
              Map Reduce Local Work

  Stage: Stage-1
    Spark
      Edges:
"        Reducer 2 <- Map 1 (GROUP, 2)"
"        Reducer 3 <- Reducer 2 (SORT, 1)"
      DagName: atguigu_20240212112407_cb09efe6-ac6e-4a57-a3a8-1b83b2fbf3a7:23
      Vertices:
        Map 1 
            Map Operator Tree: --//Stage-1的map阶段
                TableScan
                  alias: t0
                  Statistics: Num rows: 3 Data size: 9 Basic stats: COMPLETE Column stats: NONE
                  Filter Operator --// 谓词下推(where条件)表示在Tablescan的结果集上进行过滤
                    predicate: (follower_id > 2) (type: boolean) --// 过滤条件
                    Statistics: Num rows: 1 Data size: 3 Basic stats: COMPLETE Column stats: NONE
                    Map Join Operator  --//hive默认开启Map Join(set hive.map.aggr=true)
                      condition map:
                           Left Outer Join 0 to 1
                      keys:
                        0 user_id (type: int)
                        1 user_id (type: int)
"                      outputColumnNames: _col0, _col1, _col6"
                      input vertices:
                        1 Map 4
                      Statistics: Num rows: 11 Data size: 44 Basic stats: COMPLETE Column stats: NONE
                      Group By Operator --//这里是因为默认设置了hive.map.aggr=true,会在mapper先做一次预聚合,减少reduce需要处理的数据; 
"                        aggregations: count(_col0), sum(_col6)" --//分组聚合使用的算法
                        keys: _col1 (type: int) --//分组的列
                        mode: hash --// 这里的mode模式是:hash,即对key值进行hash分区,数据分发到对应的task中;
"                        outputColumnNames: _col0, _col1, _col2" --//输出的列名
                        Statistics: Num rows: 11 Data size: 44 Basic stats: COMPLETE Column stats: NONE
                        Reduce Output Operator --// 将key,value从map端输出到reduce端(key还是有序的)
                          key expressions: _col0 (type: int)
                          sort order: +   // 输出到reduce端的同时,对key值(_col)正序排序;+表示正序,-表示逆序
                          Map-reduce partition columns: _col0 (type: int) --//分区字段
                          Statistics: Num rows: 11 Data size: 44 Basic stats: COMPLETE Column stats: NONE
"                          value expressions: _col1 (type: bigint), _col2 (type: bigint)"  -- //从map端输出的value
            Execution mode: vectorized
            Local Work:
              Map Reduce Local Work
        Reducer 2 
            Execution mode: vectorized
            Reduce Operator Tree:
              Group By Operator --// reduce端的归并聚合
"                aggregations: count(VALUE._col0), sum(VALUE._col1)" --// 聚合函数的值
                keys: KEY._col0 (type: int)
                mode: mergepartial --// 此时group by的模式为mergepartial 
"                outputColumnNames: _col0, _col1, _col2"
                Statistics: Num rows: 5 Data size: 20 Basic stats: COMPLETE Column stats: NONE
                Select Operator --// 选择列,为下步的Filter Operator准备好数据
"                  expressions: _col1 (type: bigint), _col2 (type: bigint)"
"                  outputColumnNames: _col1, _col2"
                  Statistics: Num rows: 5 Data size: 20 Basic stats: COMPLETE Column stats: NONE
                  Filter Operator --//过滤
                    predicate: (_col1 > 2L) (type: boolean)
                    Statistics: Num rows: 1 Data size: 4 Basic stats: COMPLETE Column stats: NONE
                    Select Operator --// 选择列,为下步的Reduce Output Operator准备好数据
"                      expressions: _col1 (type: bigint), _col2 (type: bigint)"
"                      outputColumnNames: _col0, _col1"
                      Statistics: Num rows: 1 Data size: 4 Basic stats: COMPLETE Column stats: NONE
                      Reduce Output Operator
                        key expressions: _col1 (type: bigint)
                        sort order: +
                        Statistics: Num rows: 1 Data size: 4 Basic stats: COMPLETE Column stats: NONE
                        TopN Hash Memory Usage: 0.1
                        value expressions: _col0 (type: bigint)
        Reducer 3 
            Execution mode: vectorized
            Reduce Operator Tree:
              Select Operator
"                expressions: VALUE._col0 (type: bigint), KEY.reducesinkkey0 (type: bigint)"
"                outputColumnNames: _col0, _col1"
                Statistics: Num rows: 1 Data size: 4 Basic stats: COMPLETE Column stats: NONE
                Limit
                  Number of rows: 1
                  Statistics: Num rows: 1 Data size: 4 Basic stats: COMPLETE Column stats: NONE
                  File Output Operator  --// 输出到文件
                    compressed: false
                    Statistics: Num rows: 1 Data size: 4 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    --// limit 操作
      Processor Tree:
        ListSink

 采用可视化工具得到stage依赖图及各个stage的执行计划。stage图如下:

 工具:dist

链接:https://pan.baidu.com/s/1EruBmJPovA3A2cHRiFvQ9Q 
提取码:3kt7

使用方式:126-Hive-调优-执行计划-可视化工具_哔哩哔哩_bilibili

执行计划的理解:

  • 根据层级,从最外层开始,包含两大部分:

stage  dependencies: 各个stage之间的依赖性

stage plan: 各个stage的执行计划(物理执行计划)

  • stage plan中的有一个Map Reduce,一个MR的执行计划分为两部分:

Map Operator Tree : map端的执行计划树
Reduce Operator Tree : Reduce 端的执行计划树

  • 这两个执行计划树包含这条sql语句的算子operator:

(1)map端的首要操作是加载表,即TableScan表扫描操作,常见的属性有:

  • alisa: 表名称
  • statistics: 表统计信息,包含表中数据条数,数据大小等

(2)Select Operator:选取操作,常见的属性:

  • expressions:字段名称及字段类型
  • outputColumnNames:输出的列名称
  • Statistics:表统计信息,包含表中数据条数,数据大小等

(3)Group By Operator:分组聚合操作,常见的属性:

  • aggregations:显示聚合函数信息
  • mode:聚合模式,包括 hash;mergepartial等
  • keys:分组的字段,如果sql逻辑中没有分组,则没有此字段
  • outputColumnNames:聚合之后输出的列名
  • Statistics:表统计信息,包含分组聚合之后的数据条数,数据大小等

(4)Reduce Output Operator:输出到reduce操作,常见属性:

  • sort order :如果值是空,代表不排序;值为“+”,代表正序排序;值为“-”,代表倒序排序;值为“+-”,代表有两列参与排序,第一列是正序,第二列是倒序

(5)Filter Operator:过滤操作,常见的属性:

  • predicate: 过滤条件,如sql语句中的where id>=10,则此处显示(id >= 10)

(6)Map Join Operator:join操作,常见的属性:

  • condition map: join方式,例如有:Inner Join 、 Left Outer Join
  • keys:join的条件字段

(7)File Output Operator:文件输出操作,常见的属性:

  • compressed:是否压缩
  • table:表的信息,包含输入输出的文件格式化方式,序列化方式等

(8)Fetch Operator:客户端获取数据的操作,常见的属性:

  • limit:值为-1表示不限制条数,其他值为限制的条数

接下来拆解explain执行计划

(1)先看第一部分,代表stage之间的依赖关系

得出stage-2是根,stage-1依赖于stage-2,stage-0依赖于stage-1

(2)stage-2 阶段: 该阶段主要是对t1表进行扫描

(3)stage-1 阶段

Map阶段 1:

Map阶段:首先扫描t0表,其次谓词下推会执行where里面的过滤操作,然后执行mapjoin操作(),由于hive默认是开启预聚合操作的,所以会先在map端进行group by 分组预聚合(局部聚合),与此同时也会自动按照group by的key值进行升序排序

Reduce 2 阶段:

Reduce 2 阶段:该阶段group by分组聚合为merge操作,将分组有序的数据进行归并操作。group by 后的select操作主要是为下一步的having操作准备数据having操作会在select的结果集上做进一步的过滤。hive sql 中的select执行顺序不是固定的,但是每一次的selet操作是为下一步准备有效数据

Reduce 3 阶段:该阶段select最终结果

(4)stage-0 阶段

      该阶段主要是执行limit操作。

小结

    通过上述的explain执行计划的拆解,得出hivesql的底层执行顺序大致如下:

from->
where(谓词下推)->
join->
on->
select(select中的字段与group by只要不一致就会有)->
group by->
select(为having准备数据,因而having中可以使用select别名)->
having->
select(过滤后的结果集)->
distinct->
order by ->
select->
limit

  hive sql 中的select执行顺序不是固定的,但是每一次的selet操作是为下一步准备有效数据

2.2 案例二:Map+Reduce类型(窗口函数)

数据准备

create database exec5;
create table if not exists table1
(
    id     int comment '用户id',
    `date` string comment '用户登录时间'
);
insert overwrite table table1
values (1, '2019-01-01 19:28:00'),
       (1, '2019-01-02 19:53:00'),
       (1, '2019-01-03 22:00:00'),
       (1, '2019-01-05 20:55:00'),
       (1, '2019-01-06 21:58:00'),
       (2, '2019-02-01 19:25:00'),
       (2, '2019-02-02 21:00:00'),
       (2, '2019-02-04 22:05:00'),
       (2, '2019-02-05 20:59:00'),
       (2, '2019-02-06 19:05:00'),
       (3, '2019-03-04 21:05:00'),
       (3, '2019-03-05 19:10:00'),
       (3, '2019-03-06 19:55:00'),
       (3, '2019-03-07 21:05:00');

执行计划分析

执行如下sql语句:

--查询连续登陆3天及以上的用户(字节面试题)
explain formatted
select
    id
from (
         select
             id,
             dt,
             date_sub(dt, row_number() over (partition by id order by dt)) ds
         from ( --用户在同一天可能登录多次,需要去重
                  select
                      id,
                      --to_date():日期函数
                      -- date_format(`date`,'yyyy-MM-dd')
                      date_format(`date`, 'yyyy-MM-dd') as dt
                  from table1
                  group by id, date_format(`date`, 'yyyy-MM-dd')
              ) tmp1
     ) tmp2
group by id, ds
having count(1) >=3;

生成物理执行计划:

STAGE DEPENDENCIES: --//作业依赖关系
  Stage-1 is a root stage
  Stage-0 depends on stages: Stage-1

STAGE PLANS:
  Stage: Stage-1  --// Stage-1详细任务
    Spark  --//表示当前引擎使用的是 Spark
      Edges:
"        Reducer 2 <- Map 1 (GROUP PARTITION-LEVEL SORT, 2)"
"        Reducer 3 <- Reducer 2 (GROUP, 2)"
      DagName: atguigu_20240212153029_036d3420-d92e-436f-b78d-25a7b67525d3:44
      Vertices:
        Map 1 
            Map Operator Tree:  --//  Stage-1阶段的map执行树
                TableScan --// 扫描table1表
                  alias: table1
                  Statistics: Num rows: 14 Data size: 294 Basic stats: COMPLETE Column stats: NONE
                  Select Operator --// 选择列,为下一步 Group By Operator准备好数据
"                    expressions: id (type: int), date_format(date, 'yyyy-MM-dd') (type: string)"
"                    outputColumnNames: _col0, _col1" --// 输出的列名
                    Statistics: Num rows: 14 Data size: 294 Basic stats: COMPLETE Column stats: NONE
                    Group By Operator --// mapper端的group by,即先在 mapper端进行预聚合
"                      keys: _col0 (type: int), _col1 (type: string)"
                      mode: hash --// 对key值(_col0及_col1 )进行hash分区,数据分发到对应的task
"                      outputColumnNames: _col0, _col1" --// 输出的列名
                      Statistics: Num rows: 14 Data size: 294 Basic stats: COMPLETE Column stats: NONE
                      Reduce Output Operator --//从map端输出到reduce端
"                        key expressions: _col0 (type: int), _col1 (type: string)" --//从map端输出的key值
                        sort order: ++  --//将key及value值从map端输出到reduce端,这里的“++”代表对两个key值( _col0, _col1)都进行升序排序
                        Map-reduce partition columns: _col0 (type: int) --//分区字段
                        Statistics: Num rows: 14 Data size: 294 Basic stats: COMPLETE Column stats: NONE
            Execution mode: vectorized
        Reducer 2 
            Reduce Operator Tree: --//reduce端的执行树
              Group By Operator   --// reduce端的group by,即归并聚合
"                keys: KEY._col0 (type: int), KEY._col1 (type: string)"
                mode: mergepartial 
"                outputColumnNames: _col0, _col1"
                Statistics: Num rows: 7 Data size: 147 Basic stats: COMPLETE Column stats: NONE
                PTF Operator  --//reduce端的窗口函数分析操作
                  Function definitions:
                      Input definition
                        input alias: ptf_0
"                        output shape: _col0: int, _col1: string"
                        type: WINDOWING
                      Windowing table definition
                        input alias: ptf_1
                        name: windowingtablefunction
                        order by: _col1 ASC NULLS FIRST --//窗口函数排序列
                        partition by: _col0  --// 窗口函数分区列
                        raw input shape:
                        window functions:
                            window function definition
                              alias: row_number_window_0
                              name: row_number --//窗口函数的方法
                              window function: GenericUDAFRowNumberEvaluator
                              window frame: ROWS PRECEDING(MAX)~FOLLOWING(MAX) --//当前窗口函数上下边界
                              isPivotResult: true
                  Statistics: Num rows: 7 Data size: 147 Basic stats: COMPLETE Column stats: NONE
                  Select Operator  --//选择列,为下一步Group By Operator准备好数据
"                    expressions: _col0 (type: int), date_sub(_col1, row_number_window_0) (type: date)" --//select选择两个列,_col0, date_sub(_col1,row_number over()) 
"                    outputColumnNames: _col0, _col1"
                    Statistics: Num rows: 7 Data size: 147 Basic stats: COMPLETE Column stats: NONE
                    Group By Operator --// group by 预聚合
                      aggregations: count() --// 聚合函数 count()值
"                      keys: _col0 (type: int), _col1 (type: date)"
                      mode: hash
"                      outputColumnNames: _col0, _col1, _col2"
                      Statistics: Num rows: 7 Data size: 147 Basic stats: COMPLETE Column stats: NONE
                      Reduce Output Operator --// 输出到下一个reducer
"                        key expressions: _col0 (type: int), _col1 (type: date)"
                        sort order: ++ --// 输出到下一个reducer前,同时对两个key进行排序
"                        Map-reduce partition columns: _col0 (type: int), _col1 (type: date)"
                        Statistics: Num rows: 7 Data size: 147 Basic stats: COMPLETE Column stats: NONE
                        value expressions: _col2 (type: bigint)
        Reducer 3 
            Execution mode: vectorized
            Reduce Operator Tree:
              Group By Operator  --// group by 归并聚合
                aggregations: count(VALUE._col0)
"                keys: KEY._col0 (type: int), KEY._col1 (type: date)"
                mode: mergepartial
"                outputColumnNames: _col0, _col1, _col2"
                Statistics: Num rows: 3 Data size: 63 Basic stats: COMPLETE Column stats: NONE
                Select Operator  --//选择列,为下一步Filter Operator 准备好数据
"                  expressions: _col0 (type: int), _col2 (type: bigint)"
"                  outputColumnNames: _col0, _col2"
                  Statistics: Num rows: 3 Data size: 63 Basic stats: COMPLETE Column stats: NONE
                  Filter Operator  --//过滤条件
                    predicate: (_col2 >= 3L) (type: boolean)
                    Statistics: Num rows: 1 Data size: 21 Basic stats: COMPLETE Column stats: NONE
                    Select Operator  --//选择列,为下一步File Output Operator 准备好数据
                      expressions: _col0 (type: int)
                      outputColumnNames: _col0
                      Statistics: Num rows: 1 Data size: 21 Basic stats: COMPLETE Column stats: NONE
                      File Output Operator  --//对上面的结果集进行文件输出
                        compressed: false --//不压缩
                        Statistics: Num rows: 1 Data size: 21 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  --//limit 值为-1:表示不限制条数
      Processor Tree:
        ListSink

 采用可视化工具得到stage依赖图及各个stage的执行计划。stage图如下: 

接下来拆解explain执行计划

(1)先看第一部分,代表stage之间的依赖关系

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

得出stage-1是根,stage-0依赖于stage-1

(2)stage-1 阶段

Map阶段 1:

Map阶段:首先扫描table1表,其次select选择器会对下一步的group by 预选数据,为group by operator算子准备数据。然后在map端进行group by 分组预聚合(局部聚合),key及value值从mapper端输出到reducer端前,会自动按照的key值进行升序排序

Reduce 2 阶段:

Reduce 2 阶段:该阶段group by分组聚合为merge操作,将分组有序的数据进行归并操作。其次进行开窗操作

date_sub(dt, row_number() over (partition by id order by dt)) ds

开窗后的select选择器,逻辑如下:

select
    id,
    dt,
    date_sub(dt, row_number() over (partition by id order by dt)) ds

select选择列,主要是为下一步的 group by id, ds 分组操作准备好数据集;

Reduce 3 阶段:

(3)stage-0 阶段

      该阶段是客户端获取数据操作

小结

    上述案例主要介绍了带有窗口函数的explain执行计划分析

2.3 案例三:Map+Reduce类型(窗口函数)

数据准备

CREATE TABLE t_order (
       oid int ,
       uid int ,
       otime string,
       oamount int
 )
ROW format delimited FIELDS TERMINATED BY ",";
load data local inpath "/opt/module/hive_data/t_order.txt" into table t_order;
select * from t_order;

执行计划分析

执行如下sql语句:

explain formatted 
with tmp as (
    select
        oid,
        uid,
        otime,
        oamount,
        date_format(otime, 'yyyy-MM') as dt
    from t_order
)
select
    uid,
    --每个用户一月份的订单数
    sum(if(dt = '2018-01', 1, 0)) as    m1_count,
    --每个用户二月份的订单数
    sum(if(dt = '2018-02', 1, 0)) as    m2_count,
   -- 开窗函数
    row_number() over (partition by uid order by  sum(if(dt = '2018-01', 1, 0)))rk
from tmp
group by uid
  having m1_count >0 and m2_count=0;

生成物理执行计划:

STAGE DEPENDENCIES:--//作业依赖关系
  Stage-1 is a root stage
  Stage-0 depends on stages: Stage-1

STAGE PLANS: --//作业详细信息
  Stage: Stage-1  --//Stage-1 详细任务
    Spark  --//表示当前引擎使用的是 Spark
      Edges:
"        Reducer 2 <- Map 1 (GROUP, 2)"
"        Reducer 3 <- Reducer 2 (PARTITION-LEVEL SORT, 2)"
      DagName: atguigu_20240212174520_011afb56-73f8-49c1-9150-8399e66507c5:50
      Vertices:
        Map 1 
            Map Operator Tree: --//Stage-1 的Map阶段操作信息
                TableScan  --// 扫描表t_order
                  alias: t_order
                  Statistics: Num rows: 1 Data size: 4460 Basic stats: COMPLETE Column stats: NONE
                  Select Operator  --// 选择列,为下一步 Group By Operator准备好数据
"                    expressions: uid (type: int), date_format(otime, 'yyyy-MM') (type: string)" --//选择的两个列 uid, date_format(otime, 'yyyy-MM')
"                    outputColumnNames: _col1, _col4"  --// 输出的列名,_col1代表uid,_col4代表 date_format(otime, 'yyyy-MM')
                    Statistics: Num rows: 1 Data size: 4460 Basic stats: COMPLETE Column stats: NONE
                    Group By Operator ---// mapper端的group by,即先在 mapper端进行预聚合
"                      aggregations: sum(if((_col4 = '2018-01'), 1, 0)), sum(if((_col4 = '2018-02'), 1, 0))"  --//聚合函数算法
                      keys: _col1 (type: int)
                      mode: hash --// 对key值(_col1,即uid )进行hash分区,数据分发到对应的task
"                      outputColumnNames: _col0, _col1, _col2" --//输出的列(uid,m1_count,m2_count)
                      Statistics: Num rows: 1 Data size: 4460 Basic stats: COMPLETE Column stats: NONE
                      Reduce Output Operator --//从mapper端输出到reducer端
                        key expressions: _col0 (type: int)
                        sort order: + --//将key,value从mapper端输出到reducer端前,自动对key值(_col0)升序排序
                        Map-reduce partition columns: _col0 (type: int)
                        Statistics: Num rows: 1 Data size: 4460 Basic stats: COMPLETE Column stats: NONE
"                        value expressions: _col1 (type: bigint), _col2 (type: bigint)" --//输出value值(m1_count,m2_count)
            Execution mode: vectorized
        Reducer 2 
            Execution mode: vectorized
            Reduce Operator Tree:
              Group By Operator  --// reduce端的group by,即归并聚合
"                aggregations: sum(VALUE._col0), sum(VALUE._col1)"
                keys: KEY._col0 (type: int)
                mode: mergepartial
"                outputColumnNames: _col0, _col1, _col2"
                Statistics: Num rows: 1 Data size: 4460 Basic stats: COMPLETE Column stats: NONE
                Filter Operator --//having 过滤操作
                  predicate: ((_col1 > 0L) and (_col2 = 0L)) (type: boolean) --//过滤条件
                  Statistics: Num rows: 1 Data size: 4460 Basic stats: COMPLETE Column stats: NONE
                  Reduce Output Operator
"                    key expressions: _col0 (type: int), _col1 (type: bigint)"
                    sort order: ++
                    Map-reduce partition columns: _col0 (type: int)
                    Statistics: Num rows: 1 Data size: 4460 Basic stats: COMPLETE Column stats: NONE
        Reducer 3 
            Execution mode: vectorized
            Reduce Operator Tree:
              Select Operator --// 选择列,为下步的PTF Operator开窗分析操作准备好数据
"                expressions: KEY.reducesinkkey0 (type: int), KEY.reducesinkkey1 (type: bigint), 0L (type: bigint)" --// 选择的列为_col0, _col1, _col2,即:uid,m1_count,m2_count
"                outputColumnNames: _col0, _col1, _col2" //-- 选择的列:uid,m1_count,m2_count
                Statistics: Num rows: 1 Data size: 4460 Basic stats: COMPLETE Column stats: NONE
                PTF Operator --//reduce端的窗口函数分析操作
                  Function definitions:
                      Input definition
                        input alias: ptf_0
"                        output shape: _col0: int, _col1: bigint, _col2: bigint"
                        type: WINDOWING
                      Windowing table definition
                        input alias: ptf_1
                        name: windowingtablefunction
                        order by: _col1 ASC NULLS FIRST -//窗口函数排序列
                        partition by: _col0  --// 窗口函数分区列
                        raw input shape:
                        window functions:
                            window function definition
                              alias: row_number_window_0
                              name: row_number  --//窗口函数的方法
                              window function: GenericUDAFRowNumberEvaluator
                              window frame: ROWS PRECEDING(MAX)~FOLLOWING(MAX) --//当前窗口函数上下边界
                              isPivotResult: true
                  Statistics: Num rows: 1 Data size: 4460 Basic stats: COMPLETE Column stats: NONE
                  Select Operator --//选择列,为下一步File Output Operator准备好数据
"                    expressions: _col0 (type: int), _col1 (type: bigint), _col2 (type: bigint), row_number_window_0 (type: int)"  --// 选择的列为_col0, _col1,_col2, _col3,即:uid,m1_count,m2_count,rk
"                    outputColumnNames: _col0, _col1, _col2, _col3"
                    Statistics: Num rows: 1 Data size: 4460 Basic stats: COMPLETE Column stats: NONE
                    File Output Operator  --//对上面的结果集进行文件输出
                      compressed: false --//不压缩
                      Statistics: Num rows: 1 Data size: 4460 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  --//limit 值为-1:表示返回结果不限制条数
      Processor Tree: 
        ListSink

 采用可视化工具得到stage依赖图及各个stage的执行计划。stage图如下: 

接下来拆解explain执行计划

(1)先看第一部分,代表stage之间的依赖关系

得出stage-1是根,stage-0依赖于stage-1

(2)stage-1 阶段

Map阶段 1:

Map阶段:首先扫描 t_order表,其次select选择器会对下一步的group by 预选数据,为group by operator算子准备数据。然后在map端进行group by 分组预聚合(局部聚合),key及value值从mapper端输出到reducer端前,会自动按照的key值进行升序排序

Reduce 2 阶段:

Reduce 2 阶段:该阶段group by分组聚合为merge操作,将分组有序的数据进行归并操作。然后对分组结果进行过滤having ....,逻辑如下:

select
    uid,
    sum(if(dt = '2018-01', 1, 0)) as m1_count,
    sum(if(dt = '2018-02', 1, 0)) as m2_count
from tmp
group by uid
having m1_count >0 and m2_count=0;

Reduce 3 阶段:

Reduce 3 阶段:可以得到窗口函数的执行是在group by,having之后进行,是与select同级别的。如果SQL中既使用了group by又使用了partition by,那么此时partition by的分组是基于group by分组之后的结果集进行的再次分组,即窗口函数分析的数据范围也是基于group by后的数据。

(3)stage-0 阶段

      该阶段是客户端获取数据操作

小结

     上述案例通过对explain执行计划分析,重点验证了窗口函数与group by 之间的区别与联系,也验证了窗口函数执行顺序。

窗口函数的执行顺序: 窗口函数是作用于select后的结果集。select 的结果集作为窗口函数的输入,但是位于 distcint 之前。窗口函数的执行结果只是在原有的列中单独添加一列,形成新的列,它不会对已有的行或列做修改。简化版的执行顺序如下图:

     Hive窗口函数详细介绍见文章:

Hive窗口函数详解-CSDN博客文章浏览阅读560次,点赞9次,收藏12次。Hive窗口函数详解https://blog.csdn.net/SHWAITME/article/details/136095532?spm=1001.2014.3001.5501参考文章:

https://www.cnblogs.com/nangk/p/17649685.html

Hive Group By的实现原理_hive group by 多个字段-CSDN博客

你真的了解HiveSql吗?真实的HiveSql执行顺序是长这样的_hive 含有tablesample的sql执行顺序-CSDN博客

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C++ //练习 5.24 修改你的程序,使得当第二个数是0时抛出异常。先不要设定catch子句,运行程序并真的为除数输入0,看看会发生什么?

C Primer&#xff08;第5版&#xff09; 练习 5.24 练习 5.24 修改你的程序&#xff0c;使得当第二个数是0时抛出异常。先不要设定catch子句&#xff0c;运行程序并真的为除数输入0&#xff0c;看看会发生什么&#xff1f; 环境&#xff1a;Linux Ubuntu&#xff08;云服务器…

那些也许你不知道的操作符!

前言 操作符有很多种&#xff0c;目前我们已经了解了一部分 例如最简单的、-、*、/、&#xff0c;还有我们学到的&&&#xff0c;||&#xff0c;!等&#xff0c;但是操作符可不是就只有这么些的&#xff0c;让我们一起来看看吧 目录 1. 移位操作符 原码、反码、补码…

Ubuntu Desktop - scrolling (Terminal 缓存更多终端历史输出内容)

Ubuntu Desktop - scrolling [Terminal 缓存更多终端历史输出内容] 1. ubuntu-14.04.5-desktop-amd64.iso2. ubuntu-16.04.3-desktop-amd64.isoReferences Terminal -> 右键 Profiles -> Profile Preferences 1. ubuntu-14.04.5-desktop-amd64.iso 2. ubuntu-16.04.3-de…

手动汉化unity编辑器,解决下载中文语言报错问题

手动汉化unity编辑器&#xff0c;解决下载中文语言报错问题 START 最近在下载支持微信小程序版本的编辑器时&#xff0c;中文语言包&#xff0c;一直无法下载。记录一下 手动汉化unity编辑器的方法 &#xff0c;帮助和我遇到同样问题的人。 解决方案 1. 下载汉化包 https:…

origin技巧

origin技巧 1.去掉白边2.曲线平滑3.合并多层图例3.图例换方向 1.去掉白边 ctrlu 2.曲线平滑 3.合并多层图例 3.图例换方向 图例右键 “图例” 水平排布修改图例字&#xff1a;双击图例修改 https://blog.csdn.net/m0_47746156/article/details/121295151 https://blog.csdn.…

Ocr之TesseractOcr的安装及使用

目录 一、安装环境 二、安装内容 三、安装过程及识别测试 1. 安装过程 2. 程序编写 总结 1. 安装复杂度较低 2. 国外开源Ocr 3. 可设置识别参数 4. 工具类 一、 系统环境windows 10 linux环境也可安装, 可借鉴此篇文章>> | 二、安装内容 Tesseract exe 程序安…

CVE-2022-25578 漏洞复现

CVE-2022-25578 路由/admin/admin.php是后台&#xff0c;登录账号和密码默认是admin、tao&#xff0c;选择文件管理。 是否还记得文件上传中的.htaccess配置文件绕过发&#xff0c;在这个文件中加入一句AddType application/x-httpd-php .jpg&#xff0c;将所有jpg文件当作php…

位运算+leetcode(1)

基础 1.基础知识 以下都是针对数字的二进制进行操作 >> 右移操作符<< 左移操作符~ 取反操作符 & 有0就是0&#xff0c;全一才一 | 有一才一 &#xff0c;全0才0^ 相同为0&#xff0c;相异为1 异或( ^ )运算的规律 a ^ 0 a a ^ a 0a ^ b ^ c a ^ (b …

【Java程序设计】【C00252】基于Springboot的实习管理系统(有论文)

基于Springboot的实习管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的实习管理系统 本系统分为前台功能模块、管理员功能模块、教师功能模块、学生功能模块以及实习单位功能模块。 前台功能模块&#xf…

hook函数——useMemo

useMemo 1.useMemo定义 useMemo 是一个 React Hook&#xff0c;它在每次重新渲染的时候能够缓存计算的结果。 const 变量名 useMemo(calculateValue, dependencies) calculateValue&#xff1a;要缓存计算值的函数。它应该是一个没有任何参数的纯函数&#xff0c;并且可以返…

【程序设计竞赛】竞赛中的细节优化

必须强调下&#xff0c;以下的任意一种优化&#xff0c;都应该是在本身采用的算法没有任何问题情况下的“锦上添花”&#xff0c;而不是“雪中送炭”。 如果下面的说法存在误导&#xff0c;请专业大佬评论指正 读写优化 C读写优化——解除流绑定 在ACM里&#xff0c;经常出现…

网络协议与攻击模拟_16HTTP协议

1、HTTP协议结构 2、在Windows server去搭建web扫描器 3、分析HTTP协议流量 一、HTTP协议 1、概念 HTTP&#xff08;超文本传输协议&#xff09;用于在万维网服务器上传输超文本&#xff08;HTML&#xff09;到本地浏览器的传输协议 基于TCP/IP(HTML文件、图片、查询结构等&…

Python实现桶排序

如果在对给定的一些数据进行排序的时候&#xff0c;给定的被排序的数据存在某种特征的时候&#xff0c;我们就可以利用这种特征&#xff0c;设计出相应的排序算法&#xff0c;以达到加快排序速度的目的。 而假设要排序的数组的每个元素的取值在一个区间0,1之间随机分布&#x…

C#,卢卡斯数(Lucas Number)的算法与源代码

1 卢卡斯数&#xff08;Lucas Number&#xff09; 卢卡斯数&#xff08;Lucas Number&#xff09;是一个以数学家爱德华卢卡斯&#xff08;Edward Lucas&#xff09;命名的整数序列。爱德华卢卡斯既研究了这个数列&#xff0c;也研究了有密切关系的斐波那契数&#xff08;两个…

【开源】基于JAVA+Vue+SpringBoot的二手车交易系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 二手车档案管理模块2.3 车辆预约管理模块2.4 车辆预定管理模块2.5 车辆留言板管理模块2.6 车辆资讯管理模块 三、系统设计3.1 E-R图设计3.2 可行性分析3.2.1 技术可行性分析3.2.2 操作可行性3.2.3 经济…

如何升级至ChatGPT Plus:快速指南,ChatGPT的秘密武器GPT4.0是什么?

提到 ChatGPT。想必大家都有所耳闻。自从 2022 年上线以来&#xff0c;就受到国内外狂热的追捧和青睐&#xff0c;上线2个月&#xff0c;月活突破1个亿&#xff01;&#xff01;&#xff01; 而且还在持续上涨中。因为有很多人都在使用 ChatGPT 。无论是各大头条、抖音等 App、…

一些AI工具的初探和使用

0. 前言 目前我自己对于AI的应用还不成熟&#xff0c;先记录一下常用的AI工具&#xff0c;后续再进行探索。 目前AI发展的速度已经超出想象了。可能最开始我对ai的应用 还停留在回答问题以及自己领域的可以生成cursor,还有阿里家通义灵码。都还是程序员的范畴。 然后对于文字…

【Java程序设计】【C00264】基于Springboot的原创歌曲分享平台(有论文)

基于Springboot的原创歌曲分享平台&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的原创歌曲分享平台 本系统分为平台功能模块、管理员功能模块以及用户功能模块。 平台功能模块&#xff1a;在平台首页可以查看首…

蓝牙BLE学习-蓝牙广播

1.概念 什么叫做广播&#xff0c;顾名思义就像广场上的大喇叭一样&#xff0c;不停的向外传输着信号。不同的是&#xff0c;大喇叭传输的是音频信号&#xff0c;而蓝牙传输的是射频信号。 BLE使用的是无线电波传递信息&#xff0c;就是将数据编码&#xff0c;调制到射频信号中发…

【Java程序设计】【C00269】基于Springboot的漫画网站(有论文)

基于Springboot的漫画网站&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的漫画网站 本系统分为系统功能模块、管理员功能模块、以及用户功能模块。 系统功能模块&#xff1a;在系统首页可以查看首页、漫画投稿、…