数据仓库工具 hive的入门(九)Hive调优策略

**Hive命令实战操作之 – Hive调优策略

提示:本文章内容取自来源: 拉勾教育大数据高薪训练营




前言

提示:本文章对于初学者准备,希望对大家有所帮助。如果有什么建议和疑问,请留言给我,我会不断完成完善。


HQL操作之 – Hive调优策略

Hive作为大数据领域常用的数据仓库组件,在设计和开发阶段需要注意效率。

影响Hive效率的不仅仅是数据量过大;数据倾斜、数据冗余、job或I/O过多、MapReduce分配不合理等因素都对Hive的效率有影响。

对Hive的调优既包含对HiveQL语句本身的优化,也包含Hive配置项和MR方面的调整。

从以下三个方面展开:
架构优化
参数优化
SQL优化

第 1 节 架构优化

执行引擎

Hive支持多种执行引擎,分别是 MapReduce、Tez、Spark、Flink。可以通过hive-site.xml文件中的hive.execution.engine属性控制。

Tez是一个构建于YARN之上的支持复杂的DAG(有向无环图)任务的数据处理框架。由Hontonworks开源,将MapReduce的过程拆分成若干个子过程,同时可以把多个mapreduce任务组合成一个较大的DAG任务,减少了MapReduce之间的文件存储,同时合理组合其子过程从而大幅提升MR作业的性能。

优化器

与关系型数据库类似,Hive会在真正执行计算之前,生成和优化逻辑执行计划与物理执行计划。Hive有两种优化器:Vectorize(向量化优化器) 与 Cost-Based Optimization (CBO 成本优化器)。

  • 矢量化查询执行

    矢量化查询(要求执行引擎为Tez)执行通过一次批量执行1024行而不是每行一行来提高扫描,聚合,过滤器和连接等操作的性能,这个功能一显着缩短查询执行时间。

set hive.vectorized.execution.enabled = true;
-- 默认 false
set hive.vectorized.execution.reduce.enabled = true;
-- 默认 false
  • 成本优化器

Hive的CBO是基于apache Calcite的,Hive的CBO通过查询成本(有analyze收集的统计信息)会生成有效率的执行计划,最终会减少执行的时间和资源的利用,使用CBO的配置如下:

SET hive.cbo.enable=true; --从 v0.14.0默认
true
SET hive.compute.query.using.stats=true; -- 默认false
SET hive.stats.fetch.column.stats=true; -- 默认false
SET hive.stats.fetch.partition.stats=true; -- 默认true
分区表

对于一张比较大的表,将其设计成分区表可以提升查询的性能,对于一个特定分区的
查询,只会加载对应分区路径的文件数据,所以执行速度会比较快

分桶表

与分区表类似,分桶表的组织方式是将HDFS上的文件分割成多个文件。

分桶可以加快数据采样,也可以提升join的性能(join的字段是分桶字段),因为分桶可以确保某个key对应的数据在一个特定的桶内(文件),巧妙地选择分桶字段可以大幅度提升join的性能。

通常情况下,分桶字段可以选择经常用在过滤操作或者join操作的字段。

文件格式

在HiveQL的create table语句中,可以使用 stored as … 指定表的存储格式。

Hive表支持的存储格式有TextFile、SequenceFile、RCFile、ORC、Parquet等。

存储格式一般需要根据业务进行选择,生产环境中绝大多数表都采用TextFile、ORC、Parquet存储格式之一。

第 2 节 参数优化

参数优化方面:

本地模式
严格模式
JVM重用
并行执行
推测还行
合并小文件
Fetch模式

第 3 节 SQL优化

列裁剪和分区裁剪

列裁剪是在查询时只读取需要的列;分区裁剪就是只读取需要的分区。

简单的说:select 中不要有多余的列,坚决避免 select * from tab;

查询分区表,不读多余的数据

sort by 代替 order by

HiveQL中的order by与其他关系数据库SQL中的功能一样,是将结果按某字段全局排序,这会导致所有map端数据都进入一个reducer中,在数据量大时可能会长时间计算不完。

如果使用sort by,那么还是会视情况启动多个reducer进行排序,并且保证每个reducer内局部有序。为了控制map端数据分配到reducer的key,往往还要配合distribute by 一同使用。如果不加 distribute by 的话,map端数据就会随机分配到reducer。

group by 代替 count(distinct)

当要统计某一列的去重数时,如果数据量很大,count(distinct) 会非常慢。原因与
order by类似,count(distinct)逻辑只会有很少的reducer来处理。此时可以用group by 来改写

group by 配置调整

map端预聚合:
group by时,如果先起一个combiner在map端做部分预聚合,可以有效减少shuffle
数据量。

-- 默认为true
set hive.map.aggr = true

Map端进行聚合操作的条目数

set hive.groupby.mapaggr.checkinterval = 100000 

倾斜均衡配置项:
group by时如果某些key对应的数据量过大,就会发生数据倾斜。Hive自带了一个均衡数据倾斜的配置项 hive.groupby.skewindata ,默认值false。

其实现方法是在group by时启动两个MR job。第一个job会将map端数据随机输入reducer,每个reducer做部分聚合,相同的key就会分布在不同的reducer中。第二个job再将前面预处理过的数据按key聚合并输出结果,这样就起到了均衡的效果。

但是,配置项毕竟是死的,单纯靠它有时不能根本上解决问题,建议了解数据倾斜的细节,并优化查询语句。

join 基础优化

Hive join的三种方式
1、common join
普通连接,在SQL中不特殊指定连接方式使用的都是这种普通连接。

缺点:性能较差(要将数据分区,有shuffle)
优点:操作简单,普适性强

2、map join
map端连接,与普通连接的区别是这个连接中不会有reduce阶段存在,连接在map端完成

适用场景:大表与小表连接,小表数据量应该能够完全加载到内存,否则不适用

优点:在大小表连接时性能提升明显,

备注:Hive 0.6 的时候默认认为写在select 后面的是大表,前面的是小表, 或者使用 /+mapjoin(map_table) / 提示进行设定。select a., b. from a join b on a.id =
b.id【要求小表在前,大表之后】
hive 0.7 的时候这个计算是自动化的,它首先会自动判断哪个是小表,哪个是大表,这个参数由(hive.auto.convert.join=true)来控制,然后控制小表的大小由(hive.smalltable.filesize=25000000)参数控制(默认是25M),当小表超过这个大小,hive 会默认转化成common join。

缺点:使用范围较小,只针对大小表且小表能完全加载到内存中的情况。
3、bucket map join
分桶连接:Hive 建表的时候支持hash 分区通过指定clustered by (col_name,xxx )
into number_buckets buckets 关键字.当连接的两个表的join key 就是bucket
column 的时候,就可以通过设置hive.optimize.bucketmapjoin= true 来执行优
化。
原理:通过两个表分桶在执行连接时会将小表的每个分桶映射成hash表,每个task节点都需要这个小表的所有hash表,但是在执行时只需要加载该task所持有大表分桶对应的小表部分的hash表就可以,所以对内存的要求是能够加载小表中最大的hash块即可。

注意点:小表与大表的分桶数量需要是倍数关系,这个是因为分桶策略决定的,分桶时会根据分桶字段对桶数取余后决定哪个桶的,所以要保证成倍数关系。

优点:比map join对内存的要求降低,能在逐行对比时减少数据计算量(不用比对小表全量)

缺点:只适用于分桶表

调整 Map 数

通常情况下,作业会通过输入数据的目录产生一个或者多个map任务。主要因素包括:输入文件总数
、输入文件大小、HDFS文件块大小
map越多越好吗。当然不是,合适的才是最好的。
如果一个任务有很多小文件(<< 128M),每个小文件也会被当做一个数据块,用一个 Map Task 来完成。
一个 Map Task 启动和初始化时间 >> 处理时间,会造成资源浪费,而且系统中同时可用的map数是有限的。

对于小文件采用的策略是合并

每个map处理接近128M的文件块,会有其他问题吗。也不一定。
有一个125M的文件,一般情况下会用一个Map Task完成。假设这个文件字段很少,
但记录数却非常多。如果Map处理的逻辑比较复杂,用一个map任务去做,性能也
不好。
对于复杂文件采用的策略是增加 Map 数

调整 Reduce 数

reducer数量的确定方法比mapper简单得多。使用参数 mapred.reduce.tasks 可以
直接设定reducer数量。如果未设置该参数,Hive会进行自行推测

第 4 节 优化小结

深入理解 Hadoop 的核心能力,对Hive优化很有帮助。Hadoop/Hive 处理数据过程,有几个显著特征:

  • 不怕数据多,就怕数据倾斜
  • 对 job 数比较多的作业运行效率相对比较低,比如即使有几百行的表,多次关联多次汇总,产生十几个jobs,执行也需要较长的时间。MapReduce 作业初始化的时间是比较长的
    对sum、count等聚合操作而言,不存在数据倾斜问题
    count(distinct) 效率较低,数据量大容易出问题

从大的方面来说,优化可以从几个方面着手:

  • 好的模型设计,事半功倍 解决数据倾斜问题。
  • 仅仅依靠参数解决数据倾斜,是通用的优化手段,收获有限。开发人员应该熟悉业务,了解数据规律,通过业务逻辑解决数据倾斜往往更 可靠
  • 减少 job 数
  • 设置合理的map、reduce task数
    对小文件进行合并,是行之有效的提高Hive效率的方法
    优化把握整体,单一作业的优化不如整体最优
小结
优化时:
先从设计阶段开始
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值