HiveSQL在使用聚合类函数的时候性能分析和优化详解

这篇具有很好参考价值的文章主要介绍了HiveSQL在使用聚合类函数的时候性能分析和优化详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概述

前文我们写过简单SQL的性能分析和解读,简单SQL被归类为select-from-where型SQL语句,其主要特点是只有map阶段的数据处理,相当于直接从hive中取数出来,不需要经过行变化。在非多个节点的操作上,其性能甚至不比Tez和Spark差。

而这次我们主要说的是使用聚合类函数的hiveSQL,这类SQL需要完整的map阶段和reduce阶段才能完成数据处理。我们把它可以归类为select-aggr_function-from-where-groupby 类型SQL语句

在生产环境中我们一般常用的聚合函数见如下列表:

函数 参数格式 解释
count count(*), count(expr),count(distinct expr) 返回查找的总行数,count(*)返回的行数包括null值;count(expr)和count(distinct expr) 不包括null值
sum sum(col), sum(DISTINCT col) sum(col)返回组内查询列元素的总和,sum(DISTINCT col)返回组内查询列列的不同值的总和
avg avg(col), avg(DISTINCT col) sum(col)返回组内查询列元素的平均值,sum(DISTINCT col)返回组内查询列的不同值的平均值
min min(col) 返回组内查询列的最小值
max max(col) 返回组内查询列的最大值
variance/var_pop variance(col)/var_pop(col) 返回组内查询列的方差(也可称为总体方差),也可写成var_pop(col)
var_samp var_samp(col) 返回组内查询列方差的无偏估计(方差无偏估计中,因为估计期望损失了一个自由度,估计的分母为n-1,也可称为样本方差)
stddev_pop stddev_pop(col) 返回组内查询列的标准差
stddev_samp stddev_samp(col) 返回组内查询列标准差的无偏估计方差(无偏估计中,因为估计期望损失了一个自由度,估计的分母为n-1)
covar_pop covar_pop(col1, col2) 返回组内查询列col1和col2的总体协方差
covar_samp covar_samp(col1, col2) 返回组内查询列col1和col2的样本协方差
corr corr(col1, col2) 返回组内查询列col1和col2的相关系数
percentile percentile(BIGINT col, p) 返回组内查询整数列col所在的分位数,p可以为浮点数或数组,且其中元素大小必须在0-1之间。若col不是整数,需使用percentile_approx
percentile_approx percentile_approx(DOUBLE col, array(p1[, p2]…) [, B]) 返回组内查询列col所在的分位数,p可以为浮点数或数组,且其中元素大小必须在0-1之间。B为可选参数,为精度控制参数
regr_avgx regr_avgx(independent, dependent) 计算自变量的平均值。该函数将任意一对数字类型作为参数,并返回一个double。任何具有null的对都将被忽略。如果应用于空集:返回null。否则,它计算以下内容:avg(dependent)
regr_avgy regr_avgy(independent, dependent) 计算因变量的平均值。该函数将任意一对数字类型作为参数,并返回一个double。任何具有null的对都将被忽略。如果应用于空集:返回null。否则,它计算以下内容:avg(independent)
regr_count regr_count(independent, dependent) 返回independent和dependent都非空的对数
regr_intercept regr_intercept(independent, dependent) 返回线性回归的截距项
regr_r2 regr_r2(independent, dependent) 返回线性回归的判决系数(R方,coefficient of determination)
regr_slope regr_slope(independent, dependent) 返回线性回归的斜率系数
regr_sxx regr_sxx(independent, dependent) 等价于regr_count(independent, dependent) * var_pop(dependent)
regr_sxy regr_sxy(independent, dependent) regr_count(independent, dependent) * covar_pop(independent, dependent)
regr_syy regr_syy(independent, dependent) regr_count(independent, dependent) * var_pop(independent)
histogram_numeric histogram_numeric(col, b) 用于画直方图。返回一个长度为b的数组,数组中元素为(x,y)形式的键值对,x代表了直方图中该柱形的中心,y代表可其高度。
collect_set collect_set(col) 返回查询列col去重后的集合,与distinct不同,distinct查询结果为一列数据,collect_set查询后结果为一个集合形式的元素
collect_list collect_list(col) 返回查询列col的列表
ntile ntile(INTEGER x) 将有序分区划分为x个称为存储桶的组,并为该分区中的每一行分配存储桶编号。 (此方式存储可以快速计算分位数)

对于带聚合函数的SQL逻辑,我们可以根据其执行过程的不同,将其分成三大类来进行分析:

  • 仅在Reduce阶段聚合的SQL执行逻辑
  • 在Map和Reduce阶段都有聚合操作的SQL执行逻辑
  • 高级分组聚合的执行SQL逻辑

1.仅在Reduce阶段聚合的SQL执行逻辑

我们通过SQL执行计划来解读Reduce阶段聚合的SQL逻辑,如一下实例:

例1 在Reduce阶段进行聚合的SQL逻辑

set hive.map.aggr=false;
explain
-- 小于30岁人群的不同性别平均年龄
select gender,avg(age) as avg_age from temp.user_info_all where ymd = '20230505'
and age < 30 
group by 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
              Reduce Output Operator
                key expressions: gender (type: int)
                sort order: +
                Map-reduce partition columns: gender (type: int)
                Statistics: Num rows: 10878098 Data size: 261074352 Basic stats: COMPLETE Column stats: NONE
                value expressions: age (type: bigint)
      Reduce Operator Tree:
        Group By Operator
          aggregations: avg(VALUE._col0)
          keys: KEY._col0 (type: int)
          mode: complete
          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

以上内容的具体关键字就不作解读了,在Hive执行计划之一文读懂Hive执行计划 中已经做了完整的解释,看不懂请回看。

从上述信息中可以看到Map阶段的解析被分解为常规的三大步骤。

  • TableScan
  • Filter Operator
  • Reduce Output Operator

Reduce阶段的解析被分解为两步:

  • Group By Operator
  • File Output Operator

对比之前简单SQL执行步骤过程。

HiveSQL在使用聚合类函数的时候性能分析和优化详解

可以直观看出简单SQL的执行逻辑主要是在进行列投影后就直接将数据写入本地。而在聚合函数的SQL执行过程中使用到了Reduce阶段,多了输出到reduce阶段和分组聚合操作。

其中从map阶段输出到reduce阶段的这个流程,我们称之为数据的shuffle。后续有机会可以详细讲解其过程。

通过以上案例,可以直观的看出该SQL逻辑在map阶段没有计算的操作,只是对数据进行了一个重新组织,之后在写入reduce,即shuffle的过程进行排序,写内存,写磁盘,然后网络传输等工作。这块如果在map阶段的数据量很大,就会占用比较多的资源。

那么如何进行优化呢?

2.在map和reduce阶段聚合的SQL逻辑

以上例1,可以看到我设置了一个参数set hive.map.aggr=false;

该参数我的集群是默认开启的,为了演示我这里设置关闭。这参数本身开启后起到的作用是提前在map阶段进行数据汇总,即Combine操作。

map端数据过大一般的优化方式有两种:

  • 启用Combine操作,进行提前聚合,进而减少shuffle的数据量,减少资源消耗。
  • 启用数据压缩来减少Map和Reduce之间传输的数据量。

一般的数据压缩方式就是我们在hive上使用的数据存储格式和数据压缩方法。

启用Combine操作,在hive中提供了对应的参数,set hive.map.aggr=true;通过该配置可以控制是否启用Map端的聚合。

可以看如下例子:

例2 启用Map端聚合的SQL逻辑

同样的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;

其执行计划结果如下:

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)
                mode: hash
                outputColumnNames: _col0, _col1
                Statistics: Num rows: 10878098 Data size: 261074352 Basic stats: COMPLETE Column stats: NONE
                Reduce Output Operator
                  key expressions: _col0 (type: int)
                  sort order: +
                  Map-reduce partition columns: _col0 (type: int)
                  Statistics: Num rows: 10878098 Data size: 261074352 Basic stats: COMPLETE Column stats: NONE
                  value expressions: _col1 (type: struct<count:bigint,sum:double,input:bigint>)
      Reduce Operator Tree:
        Group By Operator
          aggregations: avg(VALUE._col0)
          keys: KEY._col0 (type: int)
          mode: mergepartial
          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

这里说明一下 value expressions: _col1 (type: struct<count:bigint,sum:double,input:bigint>)

在map阶段的最后map端最终输出的结果为一个结构体struct。其中map阶段不能计算平均值,只能计算总数和对应个数,这两者分别对应结构体中的sum和count。

将以上逻辑进行流程化。

HiveSQL在使用聚合类函数的时候性能分析和优化详解

对比例1 操作流程图,可以看出来例2 在map阶段多了一个分组聚合操作。

文字描述:先将本地节点的数据进行一个初步聚合,求出该性别的年龄相加总数和用户个数。这就已经极大的减少了数据量。之后再进行数据shuffle(分发)过程,将各个节点的数据进行汇总,之后在reduce阶段,再进行二次聚合。将各个节点的求和值和计数值汇总。在得到具体的平均值。该计算完成,输出。

以上,开启map端聚合,这也是hive在使用聚合函数过程中的最常用的一个优化方式。

hive.map.aggr=true;

那么,有一个问题,如何解决map端的数据倾斜问题?以下为常规手段。

  • 在mr程序上我们可以说开启Combine模式,进行map端聚合,hive上我们可以说开启map端聚合参数。

  • 还有,采用更优的压缩算法和数据存储格式。

思考一下,以上方式其实更多的是提供一个将大量数据变小的方式,那么map端真正的数据倾斜是什么造成的,核心该如何处理。

下一期:什么是hive的高级分组聚合,它的用法和注意事项有哪些

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

后台回复关键字 hive,随机赠送一本鲁边备注版珍藏大数据书籍。文章来源地址https://www.toymoban.com/news/detail-493438.html

到了这里,关于HiveSQL在使用聚合类函数的时候性能分析和优化详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用Profiler进行性能分析

    帧率:单位FPS,是衡量游戏性能的标准。 渲染:绘制一帧到屏幕被称为渲染一帧。 每帧花费时间=1000/[渴望的帧率] 在目标平台上的播放器中对应用程序进行性能分析 在Unity编辑器中以运行模式对应用程序进行性能分析 对Unity编辑器进行性能分析 获得有关应用程序的准确时序

    2024年02月05日
    浏览(54)
  • MySQL性能分析工具的使用

    当我们遇到数据库调优问题的时候,该如何思考呢?这里把思考的流程整理成下面这张图。 整个流程划分成了 观察( Show status ) 和 行动( Action ) 两个部分。字母 S 的部分代表观察(会使用相应的分析工具),字母 A 代表的部分是行动(对应分析可以采取的行动)。    

    2024年02月09日
    浏览(44)
  • 使用火焰图进行性能分析(一)

    分析函数执行的频度; 分析哪些函数经常阻塞; 分析哪些函数频繁操作内存; 火焰图的主要特点: 每一列代表一个调用栈,每个格子代表一个函数; 纵轴呈现出栈的深度,按照各函数的调用关系自下而上排列; 最顶端的格子代表采样时正在占用CPU的函数; 横轴:采集到的

    2024年02月05日
    浏览(54)
  • 性能测试分析与使用

    性能测试分析与使用 xx系统已经成功发布,依据之前项目的规划,计划服务1000+客户,未来势必会出现业务系统中信息大量增长的趋势。 随着该系统在生产状态下日趋稳定,也让我们可以更静下心来去关注性能方面的问题: 能够承受多大的数据量? 系统的瓶颈是什么? 代码的

    2023年04月08日
    浏览(39)
  • 解决Oracle SQL语句性能问题——SQL语句改写(分析函数、with as、union及or)

    4. 正确使用分析函数 分析函数最早出现于Oracle 8i版本中,并在后续版本中不断得以增强。正确的使用分析函数,不但能非常方便的实现某些功能,而且,在某些场景中,还可以大幅提升SQL语句的性能。因此,为了简化应用实现逻辑或解决相关SQL语句性能问题,有时我们需要利

    2024年02月10日
    浏览(34)
  • Android性能分析工具-systrace使用

    本文暂时记录使用方法,具体结合项目后续再分析。 最近研究启动优化,在此记录一下systrace工具的使用。官网资料: source.android.google.cn/devices/tec… systrace 是分析 Android 设备性能的主要工具,也是平台提供的旧版命令行工具( Android 10后引入了Perfetto),可用于获得系统跟踪

    2024年02月07日
    浏览(53)
  • 性能分析工具 之 Perfetto基本使用

            Perfetto是google从Android10开始引入的一个全新的平台级跟踪分析工具。适用于Android、Linux和Chrome的更加通用和复杂的用于性能检测和跟踪分析的生产级开源项目。在android系统中对性能分析是尤为重要的一部分,仅从logcat中进行时间分解太繁琐,android系统中可以通过

    2024年02月10日
    浏览(62)
  • ES-使用profile做性能分析

    用来查看各个组件执行时间的详细信息,但是注意,这个api不会用来测量网络延迟,请求在队列中的等待时间,以及协调节点合并各个分片响应时所花费的时间。 总体的返回结构 (1) 当前参与响应的分片,id是唯一的,格式是由 节点名 + 索引名 + 分片 组成 (2) query部分的耗时

    2024年02月09日
    浏览(36)
  • Py:代码性能分析之使用python工具—如利用cProfile【输出每个函数的运行时间和调用次数】/line_profiler【输出每行代码的执行时间】)同时对比斐波那契数列问题的递归方法和动态规划

    Py:代码性能分析之使用python工具—如利用cProfile【输出每个函数的运行时间和调用次数】/line_profiler【输出每行代码的执行时间】)同时对比斐波那契数列问题的递归方法和动态规划算法实现 目录

    2024年02月04日
    浏览(57)
  • 【MySQL高级篇笔记-性能分析工具的使用 (中) 】

    此笔记为尚硅谷MySQL高级篇部分内容 目录 一、数据库服务器的优化步骤 二、查看系统性能参数 三、统计SQL的查询成本:last_query_cost 四、定位执行慢的 SQL:慢查询日志 1、开启慢查询日志参数 2、查看慢查询数目 3、慢查询日志分析工具:mysqldumpslow 4、关闭慢查询日志 5、删除

    2024年02月07日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包