hive性能调优详解系列之hive语法和参数层面调优_数仓工程师必备hive调优方案

hive作为数仓工程师必不可缺少的计算组件,在工作中经常遇到一些调优问题,本篇文章是hive性能调优详解系列之第二篇hive语法层面调优。上一篇可点击hive建表设计层面调优

一.hive语法层面和参数调优

hive语法和参数调优将是hive调优一大重点,并能间接解决数据倾斜问题,同事提升运行效率也是重中之重。

1.1查看hive执行计划

Hive的SQL语句在执行之前需要将SQL语句转换成MapReduce任务,因此需要了解具体的转换过 程,可以在SQL语句中输入如下命令查看具体的执行计划。

##查看执行计划,添加extended关键字可以查看更加详细的执行计划 explain [extended] query

我们不仅能通过执行计划获取我们想要看到的参数,而且还能检测sql语法正确与否。

1.2.列裁剪

列裁剪就是在查询时只读取需要的列,分区裁剪就是只读取需要的分区。当列很多或者数据量很大时, 如果select * 或者前旨定分区,全列扫描和全表扫描效率都很低Hive在读数据的时候,可以只读取查询中所需要用到的列,而忽略其他的列。这样做可以节省读取开销:中间表存储开销和数据整合开销。

set hive, optimize, cp = true; ##列裁如,取数只取查询中需要用到的列,默认是true

1.3.谓词下推

将SQL语句中的where谓词逻辑都尽可能提前执行,减少下游处理的数据量。对应逻辑优化器是 PredicatePush Downo

set hive. optimize. ppd=true; ## 默认是true

示例程序:

seiect a.*, b.* from a join b on a.id = b.id where b.age > 30;
seiect a. *, c. * from a join (seiect * from b where age > 30) c on a. id = c. id;

1.4.分区裁剪

列裁剪就是在查询时只读取需要的列,分区裁剪就是只读取需要的分区。当列很多或者数据量很大时, 如果select *或者不指定分区,全列扫描和全表扫描效率都很低。
在查询的过程中只选择需要的分区,可以减少读入的分区数目,减少读入的数据量。
Hive中与分区裁剪优化相关的则是:

set hive.optimize.pruner=true; ## 默认是true

在HiveQL解析阶段对应的则是ColumnPruner逻辑优化器。

select * from student where department = “aaaa”;

1.5.合并小文件

我们都知道如果一个mapreduce job碰到一对小文件作为输入,一个小文件启动一个Task,这个本身对资源是极度浪费
Map输入合并
将输 入的小文件进行合并,从而减少mapTask任务数量。

Map端输入、合并文件之后按照block的大小分割(默认) set
hive.input.format=org.apache.hadoop.hive.ql.io.combineHivelnputFormat;
Map端输入,不合并 set
hive.input.format=org.apache.hadoop.hive.ql.io.HivelnputFormat;

Map/Reduce输出合并
大量的小文件会给HDFS带来压力,影响处哩效率。可以通过合并Map和Reduce的结果文件来消除影响。

##是否合并Map输出文件,!默认值为true set hive.merge.mapfiles=true;
##是否合并Reduce端输出文件,默认值为false set hive.merge.mapredfiles=true;
##合并文件大小,默认值为256000000 set hive.merge.size.per.task=256000000;
##每个Map最大分割大小 set mapred.max.spint.size=256000000; 一个节点上split的最少值 set map red .min. spl it.size.per. node=1; // 服务器节点 一个机架上split的最少值 set
mapred.min. split.size.per. rack=1; // 服务器机架

hive.merge.size.per.task 和 mapred.min.split.size.per.node 联合起来:

1.默认情况先把这个节点上的所有数据进行合并,如果合并的那个文件的大小超过了256M就开启另外一个文件继续合并
2.如果当前这个节点上的数据不足256M,那么就都合并成一个逻辑切片

现在有100个Task,总共有10000M的数据,平均一下,每个Task执行100M的数据的计算。
假设只启动10个Task,每个Task就要执行1000M的数据。如果只有2个Task, 5000M

1.6.合理设置MapTask井行度

一.MapReduce中的MapTask的并行度机制
Map数过大:当输入文件特别大,MapTask特别多,每个计算节点分配执行的MapTask都很多,这 时候可以考虑减少MapTask的数量。
增大每个MapTask处理的数据量。而且MapTask过多,最终生成的结果文件数也太多,所以面临两个问题

1.Map阶段输出文件太小,产生大量小文件
2.初始化和创建Map的开销很大

Map数太小:当输入文件都很大,任务逻辑复杂,MapTask执行非常慢的时候,可以考虑增加 MapTask数,来使得每个MapTask处理的数据量减少,从而提高任务的执行效率。

1.文件处理或查询并发度小,Job执行时间过长
2.大量作业时,容易堵塞集群

在MapReduce的编程案例中,我们得知,一个MapReduce Job的MapTask数量是由输入分片 Inputsplit决定的。而输入分片是由FilelnputFormat.getSplit()决定的。一仆俞入分片对应一个 MapTask,而输入分片是由三个参数决定的:

参数 默认值 意义
dfs.blocksize 128M HDFS默认块大小
mapreduce.input.fileinputformat.split.minsize 1 最小分片大小(MR)
mapreduce.input.fileinputformat.split.maxsize 256M 最大分片大小(MR)

输入分片大小的计算是这么计算出来的:

long splitsize = Math.max(minsize, Math.min(maxsize, blocksize))

默认情况下,输入分片大小和HDFS集群默认数据块大小一致,也就是默认一个数据块,启用一个 MapTask进行处理,这样做的好处是避免了服务器节点之间的数据传输,提高job处理效率
两种经典的控制MapTask的个数方案:减少MapTask数或者增加MapTask数

1.减少MapTask数是通过合并小文件来实现,这一点主要是针对数据源
2.增加MapTask数可以通过控制上一个job的reduceTask个数

重点注意:不推荐把这个值进行随意设置!
推荐的方式:使用默认的切块大小即可。如果非要调整,最好是切块的N倍数

NodeManager节点个数:N ===》Task = ( N * 0.95) * M

二.合理控制MapTask数量

1.减少MapTask数可以通过合并小文件来实现
2.增加MapTask数可以通id控制上一个ReduceTask默认的MapTask个数

计算方式
输入文件总大小:total_size
HDFS设置的数据块大小:dfs_block_size
default_mapper_num = total_size / dfs_block_size
MapReduce中提供了如下参数来控制map任务个数,从字面上看,貌似是可以直接设置MapTask个数的样子,但是很遗憾不行,这个参数设置只有在大于default_mapper_num 的时候,才会生效。

set mapred. map.tasks=10; ## 默认值是2

那如果我们需要减少MapTask数量,但是文件大小是固定的,那该怎么办呢?
可以通过mapred.min.split.size设置每个任务处理的文件的大小,这个大小只有在大于 dfs_block_size的时候才会生效

split_size = max(mapred.min.split.size, dfs_block_size) split_num =
total_size / split_size compute_map_num = Math.min(split_num,
Math.max(default_mapper_num, mapred.map.tasks))

这样就可以减少MapTask数量了。
总结一下控制mapper个数的方法:

1.如果想增加MapTask个数,可以设置mapred.map.tasks为一个较大的值
2.如果想减少MapTask个数,可以设置maperd.min.split.size为一个较大的值
3.如果输入是大量小文件,想减少mapper个数,可以通过设置hive.input.format合并小文件

如果想要调整mapper个数,在调整之前,需要确定处理的文件大概大小以及文件的存在形式(是大量 小文件,建单个大文件),然后再设置合适的参数。不能盲目进行暴力设置,不然固导其反。

1.7.合理设置ReduceTask井行度

ReduceTask数量过多
一个ReduceTask会产生一个结果文件,这样就会生成很多小文件,那么 如果这些结果文件会作为下一个Job的输入,则会出现小文件需要进行合并的问题,而且启动和初始化 ReduceTask需要耗费资源。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值