什么是hive的高级分组聚合,它的用法和注意事项以及性能分析
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的高级分组聚合,它的用法和注意事项以及性能分析的更多相关文章
- [Hive_11] Hive 的高级聚合函数
0. 说明 Hive 的高级聚合函数 union all | grouping sets | cube | rollup pv //page view 页面访问量 uv //user view 访问人 ...
- row_number() over partition by 分组聚合
分组聚合,就是先分组再排序,可以的话顺手标个排名:如果不想分组也可以排名:如果不想分组同时再去重排名也可以 ROW_NUMBER() OVER( [PARTITION BY column_1, col ...
- Atitit 数据存储的分组聚合 groupby的实现attilax总结
Atitit 数据存储的分组聚合 groupby的实现attilax总结 1. 聚合操作1 1.1. a.标量聚合 流聚合1 1.2. b.哈希聚合2 1.3. 所有的最优计划的选择都是基于现有统计 ...
- ORACLE字符串分组聚合函数(字符串连接聚合函数)
ORACLE字符串连接分组串聚函数 wmsys.wm_concat SQL代码: select grp, wmsys.wm_concat(str) grp, 'a1' str from dual un ...
- oracle 高级分组
oracle 高级分组 博客分类: 数据库基础 oraclesql 10.高级分组 本章目标: 对于增强的group by需要掌握: 1.使用rollup(也就是roll up累计的意思)操作产生s ...
- SSRS 系列 - 使用带参数的 MDX 查询实现一个分组聚合功能的报表
SSRS 系列 - 使用带参数的 MDX 查询实现一个分组聚合功能的报表 SSRS 系列 - 使用带参数的 MDX 查询实现一个分组聚合功能的报表 2013-10-09 23:09 by BI Wor ...
- MySQL最常用分组聚合函数
一.聚合函数(aggregation function)---也就是组函数 在一个行的集合(一组行)上进行操作,对每个组给一个结果. 常用的组函数: AVG([distinct] expr) 求平均值 ...
- solrcloud jsonfacet分组聚合 unique计数不准确
jsonfacet分组聚合查询 unique.hll函数问题: 对不同的值进行估算,并非准确的值, 优点:节省内存消耗,用分组算法对不同的值count进行估算 缺点:无法准确统计count(disti ...
- Oracle 高级排序函数 和 高级分组函数
高级排序函数: [ ROW_NUMBER()| RANK() | DENSE_RANK ] OVER (partition by xx order by xx) 1.row_number() 连续且递 ...
- 微软BI 之SSRS 系列 - 使用带参数的 MDX 查询实现一个分组聚合功能的报表
基于数据仓库上的 SSRS 报表展示,一般可以直接通过 SQL 查询,存储过程,视图或者表等多种方式将数据加载并呈现在报表中.但是如果是基于 Cube 多维数据集的数据查询,就不能再使用 SQL 的语 ...
随机推荐
- pandas之分组操作
在数据分析中,经常会遇到这样的情况:根据某一列(或多列)标签把数据划分为不同的组别,然后再对其进行数据分析.比如,某网站对注册用户的性别或者年龄等进行分组,从而研究出网站用户的画像(特点).在 Pan ...
- IIC总线协议—读写EEPROM
IIC总线协议-读写EEPROM 1.I2C简介 I2C 通讯协议(Inter-Integrated Circuit)是由Phiilps公司开发的,由于它引脚少,硬件实现简单,可扩展性强,不需要USA ...
- django中使用celery,模拟商品秒杀。
Celery是Python开发的简单.灵活可靠的.处理大量消息的分布式任务调度模块 安装: pip install celery # 安装celery库 pip install redis # cel ...
- 当 Amazon Lambda 遇上 Apache APISIX 可以擦出什么火花?
本文首先介绍了什么是 Serverless,以及为什么需要 Serverless:其次,讲述了一个好的网关在 Serverless 架构下的重要性,而 APISIX 就是这样的一个网关:最后,本文重点 ...
- RHEL 7配置HAProxy实现Web负载均衡
本文将简单介绍使用HAProxy实现web负载均衡,主要内容包括基于权重的轮询.为HAProxy配置https.配置http重定向为https.配置HAProxy使用独立日志. 一.测试环境 HAPr ...
- Java实现平衡二叉搜索树(AVL树)
上一篇实现了二叉搜索树,本章对二叉搜索树进行改造使之成为平衡二叉搜索树(Balanced Binary Search Tree). 不平衡的二叉搜索树在极端情况下很容易退变成链表,与新增/删除/查找时 ...
- 你还弄不清xxxForCausalLM和xxxForConditionalGeneration吗?
Part1基本介绍 大语言模型目前一发不可收拾,在使用的时候经常会看到transformers库的踪影,其中xxxCausalLM和xxxForConditionalGeneration会经常出现在我 ...
- Linux xfs文件系统stat命令Birth字段为空的原因探究
在Linux平台找出某个目录下创建时间最早的文件,测试验证脚本结果是否准确的过程中发现一个很有意思的现象,stat命令在一些平台下Birth字段有值,而在一些平台则为空值,如下所示: RHEL 8.7 ...
- selenium 多浏览器处理
开头 当我们做多浏览器自动化测试的时候,需要很多不同的浏览器,所以不同的参数对应不同的浏览器操作 目录结构 新建一个 base.py 文件, 通过 os 捕获到从命令行传进来的 import pyte ...
- 2022-04-02:你只有1*1、1*2、1*3、1*4,四种规格的砖块。 你想铺满n行m列的区域,规则如下: 1)不管那种规格的砖,都只能横着摆, 比如1*3这种规格的砖,3长度是水平
2022-04-02:你只有11.12.13.14,四种规格的砖块. 你想铺满n行m列的区域,规则如下: 1)不管那种规格的砖,都只能横着摆, 比如1*3这种规格的砖,3长度是水平方向,1长度是竖直方 ...