博客 Hive优化之SQL的优化

Hive优化之SQL的优化

   数栈君   发表于 2024-02-05 11:09  94  0

Hive是大数据领域常用的组件之一,主要是大数据离线数仓的运算,关于Hive的性能调优在日常工作和面试中是经常涉及的一个点,因此掌握一些Hive调优是必不可少的技能。影响Hive效率的主要有数据倾斜、数据冗余、job的IO以及不同底层引擎配置情况和Hive本身参数和HiveSQL的执行等因素。本文主要是从SQL角度对Hive优化抽取两个案例进行描述。

案例一 过滤前置:

案例背景

    巡检时发现有任务报错,此任务之前运行成功过,运行时长1个小时+。

问题报错分析

    根据日志可以看到任务报错主要是内存不足导致任务task被杀死,观察yarn上executor,可看到处理的数据量较大,观察客户任务sql,可以看到存在多次 join表,且是大表join。

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/9f01274ef88b177bdaf804ee2b508506..png

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/e3f50fc2f832b7f58800aa9d51a41102..png

任务sql:

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/b7051b8619fa6c39dcc83a4b0349f0cd..png

解决优化

    开始时尝试调大内存参数,仍是报错。考虑数据处理量太大,且看客户sql是join后再where过滤,建议客户将过滤前置到每个join内部,并且调大spark.sql.shuffle.partitions参数为1000(默认是200),观察任务运行成功,耗时13分钟。

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/d5b41a8ddd6511710542ac762699a45f..png

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/2dd6965244cbe78d35baaa00924779fd..png

案例二 谨防过度优化:

案例背景

    客户反馈有一任务运行缓慢,占据资源严重,希望我们能针对这个任务提供一下优化。

运行缓慢分析

    查看sql语句,主要是使用的group by针对不同年龄段的用户实现的去重的功能,且该任务数据量较多。

    sql语句有个比较常见的优化手段:利用group by代替distinct实现去重,因为在数据量比较大的情况下,使用group by能有效的避免数据倾斜,执行效率更高。但其实在设置测试数据进行测试中,group by比distinct的效率还低。

    创建表模拟测试场景,将group by和distinct执行效率进行比较:

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/bf1057bfde8e0f08fd20998dd071058a..png

http://dtstack-static.oss-cn-hangzhou.aliyuncs.com/2021bbs/files_user1/article/df0e8d23659cc1f134b8e0172d468349..png

    原因有以下几点:

    1、进行去重的列是s_age列,他的含义表示年龄,一个人的年龄是有限的,转化为MapReduce来解释的话,在Map阶段,每个Map会对年龄进行去重,由于一个人年龄不可能无限制的大或小,因此每个Map得到的s_age也有限,最终得到的reducce的数量去重过的s_age的个数,数据量上比较小,不需要避免数据倾斜。

    2、在第二个语句中distinct的命令在内存中会构建一个hashtable,查找去重的时间复杂度是O(1),而group by 在不同版本间变动较大,有的版本会用hashtable进行去重,有的版本则是使用排序的方式去重,这种排序方式是达不到O(1)。

    3、最新的hive版本中针对count(distinct) 进行了优化,通过设置参数,即使出现数据倾斜,内部也会进行自动优化,自动改变sql的执行计划。

    从执行计划中也可以证明这个结论

    语句1的执行计划:

SQL
STAGE DEPENDENCIES:
Stage-1 is a root stage
Stage-2 depends on stages: Stage-1
Stage-0 depends on stages: Stage-2

STAGE PLANS:
Stage: Stage-1
Map Reduce
Map Operator Tree:
TableScan
alias: student_tb_txt
Statistics: Num rows: 5482188 Data size: 43857508 Basic stats: COMPLETE Column stats: NONE
Select Operator
expressions: s_age (type: bigint)
outputColumnNames: s_age
Statistics: Num rows: 5482188 Data size: 43857508 Basic stats: COMPLETE Column stats: NONE
Group By Operator
keys: s_age (type: bigint)
mode: hash
outputColumnNames: _col0
Statistics: Num rows: 5482188 Data size: 43857508 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: 5482188 Data size: 43857508 Basic stats: COMPLETE Column stats: NONE
Reduce Operator Tree:
Group By Operator
keys: KEY._col0 (type: bigint)
mode: mergepartial
outputColumnNames: _col0
Statistics: Num rows: 2741094 Data size: 21928754 Basic stats: COMPLETE Column stats: NONE
Select Operator
Statistics: Num rows: 2741094 Data size: 21928754 Basic stats: COMPLETE Column stats: NONE
Group By Operator
aggregations: count(1)
mode: hash
outputColumnNames: _col0
Statistics: Num rows: 1 Data size: 8 Basic stats: COMPLETE Column stats: NONE
File Output Operator
compressed: false
table:
input format: org.apache.hadoop.mapred.SequenceFileInputFormat
output format: org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat
serde: org.apache.hadoop.hive.serde2.lazybinary.LazyBinarySerDe

Stage: Stage-2
Map Reduce
Map Operator Tree:
TableScan
Reduce Output Operator
sort order:
Statistics: Num rows: 1 Data size: 8 Basic stats: COMPLETE Column stats: NONE
value expressions: _col0 (type: bigint)
Reduce Operator Tree:
Group By Operator
aggregations: count(VALUE._col0)
mode: mergepartial
outputColumnNames: _col0
Statistics: Num rows: 1 Data size: 8 Basic stats: COMPLETE Column stats: NONE
File Output Operator
compressed: false
Statistics: Num rows: 1 Data size: 8 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

语句2的执行计划:

SQL
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: student_tb_txt
Statistics: Num rows: 5482188 Data size: 43857508 Basic stats: COMPLETE Column stats: NONE
Select Operator
expressions: s_age (type: bigint)
outputColumnNames: s_age
Statistics: Num rows: 5482188 Data size: 43857508 Basic stats: COMPLETE Column stats: NONE
Group By Operator
aggregations: count(DISTINCT s_age)
keys: s_age (type: bigint)
mode: hash
outputColumnNames: _col0, _col1
Statistics: Num rows: 5482188 Data size: 43857508 Basic stats: COMPLETE Column stats: NONE
Reduce Output Operator
key expressions: _col0 (type: bigint)
sort order: +
Statistics: Num rows: 5482188 Data size: 43857508 Basic stats: COMPLETE Column stats: NONE
Reduce Operator Tree:
Group By Operator
aggregations: count(DISTINCT KEY._col0:0._col0)
mode: mergepartial
outputColumnNames: _col0
Statistics: Num rows: 1 Data size: 16 Basic stats: COMPLETE Column stats: NONE
File Output Operator
compressed: false
Statistics: Num rows: 1 Data size: 16 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

    对比以上两个语句的执行计划,我们可以看出语句1是将去重和计数放到两个MapReduce中进行处理的,首先在第一个MapReduce阶段实现了select s_age from ods.student_tb_txt group by s_age的工作,在后面的MapReduce作业中实现了select count(1) from (..)b的逻辑。语句2是将去重和计数放在一个MapReduce中完成,相比语句1,消耗的磁盘及网络I/O也会更少。

解决优化

    结合业务和执行计划,使用distinct和group by实现去重功能。

总结: 

    调优要讲究适时调优,过早的进行调优可能导致过犹不及的效果,很多调优尤其是针对SQL的调优都是要基于业务出发,适合的才是最好的




《数据治理行业实践白皮书》下载地址:
https://fs80.cn/4w2atu

《数栈V6.0产品白皮书》下载地址:https://fs80.cn/cw0iw1

想了解或咨询更多有关袋鼠云大数据产品、行业解决方案、客户案例的朋友,浏览袋鼠云官网:https://www.dtstack.com/?src=bbs

同时,欢迎对大数据开源项目有兴趣的同学加入「袋鼠云开源框架钉钉技术群」,交流最新开源技术信息,群号码:30537511,项目地址:https://github.com/DTStack  

0条评论
社区公告
  • 大数据领域最专业的产品&技术交流社区,专注于探讨与分享大数据领域有趣又火热的信息,专业又专注的数据人园地

最新活动更多
微信扫码获取数字化转型资料
钉钉扫码加入技术交流群