hive的高级分组聚合是指在聚合时使用GROUPING SETS、CUBE和ROLLUP的分组聚合。

高级分组聚合在很多数据库类SQL中都有出现,并非hive独有,这里只说明hive中的情况。

使用高级分组聚合不仅可以简化SQL语句,而且通常情况下会提升SQL语句的性能。

1.Grouping sets 的使用

示例:

-- 使用方式
select a,b,sum(c) from tbl group by a,b grouping sets(a,b)

Grouping sets的子句允许在一个group by 语句中,指定多个分组聚合列。所有含有Grouping sets 的子句都可以用union连接的多个group by 查询逻辑来表示。

如下一些常见的等价替换示例:

-- 语句1
select a, b sum(c) from tbl group by a,b grouping sets((a,b))
-- 相当于
select a,b,sum(c) from tbl group by a,b -- 语句2
select a,b,sum(c) from tbl group by a,b grouping sets((a,b),a)
-- 相当于
select a,b,sum(c) from tbl group by a,b
union
select a,null ,sum(c) from tbl group by a -- 语句3
select a,b,sum(c) from tbl group by a,b grouping sets(a,b)
-- 相当于
select a,null,sum(c) from tbl group by a
union
select null ,b,sum(c) from tbl group by b -- 语句4
select a,b,sum(c) from tbl group by a,b grouping sets((a,b),a,b,())
-- 相当于
select a,b,sum(c) from tbl group by a,b
union
select a,null,sum(c) from tbl group by a
union
select null,b,sum(c) from tbl group by b
union
select null,null,sum(c) from tbl

可以看到通过等价替换的改写之后,语句会变得简洁,性能我们之后分析。

2.cube 和rollup的使用

示例:

-- cube使用示例
select a,b,c,count(1) from tbl group by a,b,c with cube
-- rollup使用示例
select a,b,c,count(1) from tbl group by a,b,c with rollup

用法说明:

以上两个高级分组函数都可以在一个group by 语句中完成多个分组聚合,它们都可以用grouping sets来等价替换。

  • cube 会计算所有group by 列的所有组合
-- cube语句
select a,b,c,count(1) from tbl group by a,b,c with cube
-- 相当于
select a,b,c count(1) from tbl group by a,b,c
grouping sets((a,b,c),(a,b),(b,c),(a,c),(a),(b),(c),())
  • rollup 会按照group by 指定的列从左到右进行分组聚合
-- rollup语句 滚动式聚合
select a,b,c,count(1) from tbl group by a,b,c with rollup
-- 相当于
select a,b,c,count(1) from tbl group by a,b,c s
grouping sets((a,b,c),(a,b),(a),())

3.使用高级分组聚合函数的性能分析

我们可以通过执行计划的执行来分析高级分组聚合SQL语句的执行过程,比对其优化的节点。

例1 含grouping sets关键词的SQL执行案例。

set hive.map.aggr=true;
explain
-- 小于30岁人群的不同性别平均年龄
select gender,avg(age) as avg_age from temp.user_info_all where ymd = '20230505'
and age < 30
group by gender; -- 将以上语句改为grouping sets关键词执行语句
set hive.map.aggr=true;
explain
select gender,avg(age) as num from temp.user_info_all
where ymd = '20230505'
and age < 30
group by gender grouping sets((gender));

查看其执行计划:

STAGE DEPENDENCIES:
Stage-1 is a root stage
Stage-0 depends on stages: Stage-1 STAGE PLANS:
Stage: Stage-1
Map Reduce
Map Operator Tree:
TableScan
alias: user_info_all
Statistics: Num rows: 32634295 Data size: 783223080 Basic stats: COMPLETE Column stats: NONE
Filter Operator
predicate: (age < 30) (type: boolean)
Statistics: Num rows: 10878098 Data size: 261074352 Basic stats: COMPLETE Column stats: NONE
Group By Operator
aggregations: avg(age)
keys: gender (type: int), 0 (type: int)
mode: hash
outputColumnNames: _col0, _col1, _col2
Statistics: Num rows: 10878098 Data size: 261074352 Basic stats: COMPLETE Column stats: NONE
Reduce Output Operator
key expressions: _col0 (type: int), _col1 (type: int)
sort order: ++
Map-reduce partition columns: _col0 (type: int), _col1 (type: int)
Statistics: Num rows: 10878098 Data size: 261074352 Basic stats: COMPLETE Column stats: NONE
value expressions: _col2 (type: struct<count:bigint,sum:double,input:bigint>)
Reduce Operator Tree:
Group By Operator
aggregations: avg(VALUE._col0)
keys: KEY._col0 (type: int), KEY._col1 (type: int)
mode: mergepartial
outputColumnNames: _col0, _col2
Statistics: Num rows: 5439049 Data size: 130537176 Basic stats: COMPLETE Column stats: NONE
pruneGroupingSetId: true
Select Operator
expressions: _col0 (type: int), _col2 (type: double)
outputColumnNames: _col0, _col1
Statistics: Num rows: 5439049 Data size: 130537176 Basic stats: COMPLETE Column stats: NONE
File Output Operator
compressed: true
Statistics: Num rows: 5439049 Data size: 130537176 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

对以上内容进行关键字解读:

map阶段:

  • Group By Operator :Map端开启聚合操作
  • aggregations:分组聚合的算法,该案例采取avg(age)
  • keys: 这里是分组列+ 一个固定列 0
  • mode:Hash
  • outputColumnNames:最终输出三列。_col0, _col1, _col2
  • Reduce Output Operator:该阶段为map阶段聚合后的操作
  • key expressions:map端最终输出的key,该例为gender和0两列。
  • sort order:输出两列都正序排序
  • Map-reduce partition columns:表示Map阶段数据输出的分区列,该案例为gender和0两列进行分区。
  • value expressions:map端最终输出value,为一个结构体。

Reduce阶段:

  • Group By Operator:reduce阶段的分组聚合操作。
  • aggregations: 分组聚合算法,avg(VALUE._col0)表示对map阶段输出的 value expressions的 _col0取平均值。
  • keys:指定分组聚合的key,有两列。为map阶段输出的key。
  • mode: mergepartial
  • outputColumnNames: 表示最终输出的列,该例为gender和num。
  • pruneGroupingSetId: 表示是否对最终输出的grouping id进行修剪,如果为true,则表示将keys最后一列抛弃。案例中为0列。
  • Select Operator:进行列投影操作。
  • expressions:输出的列。gender和num。

通过查看以上的执行计划,可以看出在使用含有grouping sets语句的SQL中,hive执行计划并没有给出具体的实现细节。

再执行具有多个聚合列的实例来看看:

例2 聚合年龄和聚合性别多列合并测试。

set hive.map.aggr=true;
explain
select gender,age,count(0) as num from temp.user_info_all
where ymd = '20230505'
and age < 30
group by gender,age grouping sets(gender,age);

注:grouping sets后进行分组的列一定要在之前的group by中进行申明。

STAGE DEPENDENCIES:
Stage-1 is a root stage
Stage-0 depends on stages: Stage-1 STAGE PLANS:
Stage: Stage-1
Map Reduce
Map Operator Tree:
TableScan
alias: user_info_all
Statistics: Num rows: 32634295 Data size: 783223080 Basic stats: COMPLETE Column stats: NONE
Filter Operator
predicate: (age < 30) (type: boolean)
Statistics: Num rows: 10878098 Data size: 261074352 Basic stats: COMPLETE Column stats: NONE
Group By Operator
aggregations: count(0)
keys: gender (type: int), age (type: bigint), 0 (type: int)
mode: hash
outputColumnNames: _col0, _col1, _col2, _col3
Statistics: Num rows: 21756196 Data size: 522148704 Basic stats: COMPLETE Column stats: NONE
Reduce Output Operator
key expressions: _col0 (type: int), _col1 (type: bigint), _col2 (type: int)
sort order: +++
Map-reduce partition columns: _col0 (type: int), _col1 (type: bigint), _col2 (type: int)
Statistics: Num rows: 21756196 Data size: 522148704 Basic stats: COMPLETE Column stats: NONE
value expressions: _col3 (type: bigint)
Reduce Operator Tree:
Group By Operator
aggregations: count(VALUE._col0)
keys: KEY._col0 (type: int), KEY._col1 (type: bigint), KEY._col2 (type: int)
mode: mergepartial
outputColumnNames: _col0, _col1, _col3
Statistics: Num rows: 10878098 Data size: 261074352 Basic stats: COMPLETE Column stats: NONE
pruneGroupingSetId: true
Select Operator
expressions: _col0 (type: int), _col1 (type: bigint), _col3 (type: bigint)
outputColumnNames: _col0, _col1, _col2
Statistics: Num rows: 10878098 Data size: 261074352 Basic stats: COMPLETE Column stats: NONE
File Output Operator
compressed: true
Statistics: Num rows: 10878098 Data size: 261074352 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

通过以上两个例子可以看出hive执行计划中没有具体的高级分组聚合如何实现分组方案。两者执行方式基本上差不多。

在数据扫描和查询上的确减少了多次数据扫描和数据io操作。在一定程度上节省了计算资源。

例3 使用cube替代grouping sets 。

set hive.map.aggr=true;
explain
select gender,age,count(0) as num from temp.user_info_all
where ymd = '20230505'
and age < 30
group by gender,age with cube; -- 等价语句
select gender,age,count(0) as num from temp.user_info_all
where ymd = '20230505'
and age < 30
group by gender,age grouping sets((gender,age),(gender),(age),());
STAGE DEPENDENCIES:
Stage-1 is a root stage
Stage-0 depends on stages: Stage-1 STAGE PLANS:
Stage: Stage-1
Map Reduce
Map Operator Tree:
TableScan
alias: user_info_all
Statistics: Num rows: 32634295 Data size: 783223080 Basic stats: COMPLETE Column stats: NONE
Filter Operator
predicate: (age < 30) (type: boolean)
Statistics: Num rows: 10878098 Data size: 261074352 Basic stats: COMPLETE Column stats: NONE
Group By Operator
aggregations: count(0)
keys: gender (type: int), age (type: bigint), 0 (type: int)
mode: hash
outputColumnNames: _col0, _col1, _col2, _col3
Statistics: Num rows: 43512392 Data size: 1044297408 Basic stats: COMPLETE Column stats: NONE
Reduce Output Operator
key expressions: _col0 (type: int), _col1 (type: bigint), _col2 (type: int)
sort order: +++
Map-reduce partition columns: _col0 (type: int), _col1 (type: bigint), _col2 (type: int)
Statistics: Num rows: 43512392 Data size: 1044297408 Basic stats: COMPLETE Column stats: NONE
value expressions: _col3 (type: bigint)
Reduce Operator Tree:
Group By Operator
aggregations: count(VALUE._col0)
keys: KEY._col0 (type: int), KEY._col1 (type: bigint), KEY._col2 (type: int)
mode: mergepartial
outputColumnNames: _col0, _col1, _col3
Statistics: Num rows: 21756196 Data size: 522148704 Basic stats: COMPLETE Column stats: NONE
pruneGroupingSetId: true
Select Operator
expressions: _col0 (type: int), _col1 (type: bigint), _col3 (type: bigint)
outputColumnNames: _col0, _col1, _col2
Statistics: Num rows: 21756196 Data size: 522148704 Basic stats: COMPLETE Column stats: NONE
File Output Operator
compressed: true
Statistics: Num rows: 21756196 Data size: 522148704 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

以上例3 cube语句和例2语句输出数据完全是不一样的。但其输出执行计划内容基本和例2一致。可以看出hive的执行计划对高级分组聚合拆分执行计划的支持还不是很好。

使用高级分组聚合,要注意开启map端聚合模式。

使用高级分组聚合,如上案例,仅使用一个作业就能够实现union写法需要多个作业才能实现的逻辑。

从这点上来看能够减少多个作业在磁盘和网络I/O时的负担,是一种优化。

但是同时也要注意因过度使用高级分组聚合语句而导致的数据急速膨胀问题。

  • 通常使用简单的group by 语句,一份数据只有一种聚合结果,一个分组聚合通常只有一个记录;

  • 使用高级分组聚合,例如cube,在一个作业中一份数据会存在多种聚合情况,最终输出是,每种聚合情况各自对应一条数据。

注意事项:

如果使用高级分组聚合的语句处理的底表,在数据量很大的情况下容易导致Map或者Reduce任务因硬件资源不足而崩溃。

hive中使用hive.new.job.grouping.set.cardinality 配置项来应对以上情况。

如果SQL语句中处理分组聚合情况超过该配置项指定的值,默认值为(30),则会创建一个新的作业。

下一期:hive窗口分析函数解读以及带窗口分析函数的SQL性能分析

按例,欢迎点击此处关注我的个人公众号,交流更多知识。

后台回复关键字 hive,随机赠送一本鲁边备注版珍藏大数据书籍。

什么是hive的高级分组聚合,它的用法和注意事项以及性能分析的更多相关文章

  1. [Hive_11] Hive 的高级聚合函数

    0. 说明 Hive 的高级聚合函数 union all | grouping sets | cube | rollup pv //page view 页面访问量 uv //user view 访问人 ...

  2. row_number() over partition by 分组聚合

    分组聚合,就是先分组再排序,可以的话顺手标个排名:如果不想分组也可以排名:如果不想分组同时再去重排名也可以 ROW_NUMBER() OVER( [PARTITION BY column_1, col ...

  3. Atitit  数据存储的分组聚合 groupby的实现attilax总结

    Atitit  数据存储的分组聚合 groupby的实现attilax总结 1. 聚合操作1 1.1. a.标量聚合 流聚合1 1.2. b.哈希聚合2 1.3. 所有的最优计划的选择都是基于现有统计 ...

  4. ORACLE字符串分组聚合函数(字符串连接聚合函数)

    ORACLE字符串连接分组串聚函数 wmsys.wm_concat SQL代码: select grp, wmsys.wm_concat(str) grp, 'a1' str from dual un ...

  5. oracle 高级分组

    oracle 高级分组 博客分类: 数据库基础 oraclesql  10.高级分组 本章目标: 对于增强的group by需要掌握: 1.使用rollup(也就是roll up累计的意思)操作产生s ...

  6. SSRS 系列 - 使用带参数的 MDX 查询实现一个分组聚合功能的报表

    SSRS 系列 - 使用带参数的 MDX 查询实现一个分组聚合功能的报表 SSRS 系列 - 使用带参数的 MDX 查询实现一个分组聚合功能的报表 2013-10-09 23:09 by BI Wor ...

  7. MySQL最常用分组聚合函数

    一.聚合函数(aggregation function)---也就是组函数 在一个行的集合(一组行)上进行操作,对每个组给一个结果. 常用的组函数: AVG([distinct] expr) 求平均值 ...

  8. solrcloud jsonfacet分组聚合 unique计数不准确

    jsonfacet分组聚合查询 unique.hll函数问题: 对不同的值进行估算,并非准确的值, 优点:节省内存消耗,用分组算法对不同的值count进行估算 缺点:无法准确统计count(disti ...

  9. Oracle 高级排序函数 和 高级分组函数

    高级排序函数: [ ROW_NUMBER()| RANK() | DENSE_RANK ] OVER (partition by xx order by xx) 1.row_number() 连续且递 ...

  10. 微软BI 之SSRS 系列 - 使用带参数的 MDX 查询实现一个分组聚合功能的报表

    基于数据仓库上的 SSRS 报表展示,一般可以直接通过 SQL 查询,存储过程,视图或者表等多种方式将数据加载并呈现在报表中.但是如果是基于 Cube 多维数据集的数据查询,就不能再使用 SQL 的语 ...

随机推荐

  1. 一文了解MySQL中的多版本并发控制

    作者:京东零售  李泽阳 最近在阅读<认知觉醒>这本书,里面有句话非常打动我:通过自己的语言,用最简单的话把一件事情讲清楚,最好让外行人也能听懂. 也许这就是大道至简,只是我们习惯了烦琐和 ...

  2. The first week match's mistake-2

    旋转排列 (https://www.luogu.com.cn/problem/B3688) 解读一下题目: 要求从给定的数组拿出最后一个数字后 看看变化后的数组的最后一个数字是否是要求的数字 想到用栈 ...

  3. 深度学习基础5:交叉熵损失函数、MSE、CTC损失适用于字识别语音等序列问题、Balanced L1 Loss适用于目标检测

    深度学习基础5:交叉熵损失函数.MSE.CTC损失适用于字识别语音等序列问题.Balanced L1 Loss适用于目标检测 1.交叉熵损失函数 在物理学中,"熵"被用来表示热力学 ...

  4. 回车,换行,转义字符“\r”,“\n”是什么关系?

    1."回车"这个名词的来历. 关于"回车键"的来历,还得从机械英文打字机说起.在机械英文打字机上,有一个部件叫"字车",每打一个字符(原为单 ...

  5. [C++基础入门] 6、 函数

    文章目录 6 函数 6.1 概述 6.2 函数的定义 6.3 函数的调用 6.4 值传递 6.5 函数的常见样式 6.6 函数的声明 6.7 函数的分文件编写 6 函数 6.1 概述 **作用:**将 ...

  6. NC51101 Lost Cows

    题目链接 题目 题目描述 \(N (2 \leq N \leq 8,000)\) cows have unique brands in the range 1..N. In a spectacular ...

  7. git仓库过渡,同时向两个仓库推送代码

    公司部门被大佬收购,产品项目迁移新公司仓库,过渡期间产品上线流程继续使用原公司的,新公司部署新系统后通过域名重定向逐渐将用户引流到新系统上完成切换,最后关闭原公司系统及上线流程. 过渡期间新功能代码需 ...

  8. 一个好用的java图片缩放及质量压缩方法

    本文中代码来自:http://blog.csdn.net/liuhuanchao/article/details/50527856由于网站需要对上传的图片进行宽度判断缩放和质量压缩,以提升整体加载速度 ...

  9. 基于APM模式的异步实现及跨线程操作窗体或控件方法的实现示例

    最近在一家某电力外派公司开发相关于GIS的功能,在实现代码的过程中出现了一些常见的问题比如: 1.跨线程执行窗体或控件操作(直接使用委拖) 2.异步模式执行某长时间耗时方法 经过一系列摸索可算找到解决 ...

  10. Grafana系列-统一展示-8-ElasticSearch日志快速搜索仪表板

    系列文章 Grafana 系列文章 概述 我们是基于这篇文章: Grafana 系列文章(十二):如何使用 Loki 创建一个用于搜索日志的 Grafana 仪表板, 创建一个类似的, 但是基于 El ...