Hive 调优总结

前言

调优须知

  1. Hive 一个常用的大数据组件,影响它的性能的从来都不是因为数据量过大的问题,而是数据倾斜,冗余,Job 和 IO 过多,MapReduce 分配不合理···等等

所以我们可以从它的 建表设计,HiveSQL优化,组件配置参数和底层的 MapReduce 这几个方面进行调整,总之就是在保证业务结果不变的前提下,尽可能降低资源的损耗及任务的运行时间。

  1. HiveSQL 底层会转换层多个 Job 并行串行执行,Job 数较多的作业自然会慢,就算你的表数据量很小,由于 MapReduce 作业初始化的时间十分长,所以它耗时也会很长

  2. Hive 进行大数据分析时,mapper 阶段的局部聚合和两阶段聚合可以解决常见的类似于 sum ,count,max/min UDAF 所造成的数据倾斜问题,当然如果是 join 的情况就会更为复杂

  3. 好的建表设计也算是一种优化

  4. 设置一个合理的 Task 并行度可以有效提升性能

  5. 直接了解数据分布,针对性处理也是不错的方法

  6. 数据量很大的情况使用 count(distinct),group by 很容易出问题,但是 group by 和聚合类操作一起使用的话,问题不会很大。

  7. 对小文件合并,还有调优手段本身就是针对资源不足的情况下产生的,所以,一切的调优手段都比不上直接加资源来的最简单粗暴,要是直接能加机器,那就别想太多了😂

一、建表设计层面

1.1 分区表与分桶表

我们都听过内部表,外部表,分区表,分桶表,内部表和外部表在性能上是没有什么区别的,分区表就是在某几个维度对数据进行分类存储,一个分区对应一个目录,当你查询的时候带有分区字段,那么 Hive 只需要遍历对应的分区目录(其实就是一个 HDFS 的目录)即可。这样属于减少了处理的数据量,例如

select ··· where day = '昨天'

我们的 Hive 表很多都是按天进行分区的,但假如当时建的不是分区表,那我们查询的时候,就还是会遍历所有的数据,然后筛选出昨天产生的数据,但是如果是分区表的话,它查询的时候就直接去昨天的文件夹那里拿了。

所以一张表如果大部分情况下都是使用这个字段进行 where 过滤的话,记得将此表改成分区表

分桶和分区的概念稍稍有些不一样,它是将数据以指定列的值作为 key 进行 Hash 到指定数目的桶中。道理也是避免遍历所有的数据,例如

select a.*,b.* from a join b on a.id = b.id

此时如果a,b为两张大表这个任务的执行效率势必会成为问题,还有可能存在数据倾斜。此时如果a表的 id 经常用于做 join 查询,那此时就应该把 a 表设计为分桶表,并把 id 作为分桶字段。

而且这样可以方便之后对数据进行采样

这里顺带提一下最近兴起的 Doris ,它也是一个 OLAP 引擎,它里面就会有一个 colocation join,上面的例子中,分桶其实隐藏了两个条件,一个是a,b表都必须是分桶表,还有就是它俩的分桶数量必须成倍数关系。而 Doris 中则要求它们的 分桶数量 相等,这样它能保证 两张表相同分桶编号的数据,在同一个节点上

顺带一提 Doris 的 SQL 的执行效率是会比 Hive 高很多的。且常见的 OLAP 引擎一般会存在下面的优势:列存储 + 范围分区 + 排序 + 索引 + 压缩 + 预结算 + 数据倾斜解决方案

1.2 合适的存储格式

Hive 默认存储格式为 TextFile,例如 student(id,name,sex,department····100个字段)

select department,count(*) as total from student group by department

此时我们就会发现,其实我们根本就没用到除了 department 以外的属性,那此时如果我们是列存储的话,就可以避免每次读取一条数据时都附带上了 student 所有的字段。那此时如果我们是使用 100 个文件来分别存储 student 表的 100 个属性,就可以解决我们的问题了。

所以在遇到宽表时,尽量使用 orc,parquet 这两种列式存储格式,因为列式存储的表每一列的数据在物理层面上是存储在一起的。这样能只处理 1/100 的数据量

1.3 合适的压缩格式

压缩算法需要判断当前任务为 IO 密集型,还是计算密集型。如果是 IO 密集型的任务,大量的资源用在这块的话,压缩才可以考虑。当然我们这时候会用 CPU 的资源去换网络资源,所以我们还必须保证这时候的 CPU 资源够用才行。如果是计算密集型的任务,那就不能再给 CPU 加重负担了。

压缩算法的选择就从 压缩率,压缩速率,是否可拆分 来判断。一个文件,被压缩之后会变成类似于这样的格式

header + body

header 是存放元数据信息的,而 body 是真实数据,header 会记录数据压缩前后的大小及压缩的算法···等相关信息,只有这样在解压缩的时候才知道使用哪种算法来解。而可拆分和不可拆分就是指这个 header 的元数据信息,在原来的真实数据被切分之后,会不会给每个切分出来的块都保留一份 header 。以避免之后无法进行解压缩的问题

压缩格式 是否可拆分 是否自带 压缩率 速度 是否 Hadoop 自带
gzip 很高 比较快
lzo 比较高 很快
snappy 比较高 很快
bzip2 最高
1.3.1 压缩使用

Job 输出文件按照 Block 以 GZip 的方式进行压缩:

## 默认值是false
set mapreduce.output.fileoutputformat.compress=true;   

## 默认值是Record
set mapreduce.output.fileoutputformat.compress.type=BLOCK 

## 默认值是org.apache.hadoop.io.compress.DefaultCodec
set mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.G
zipCodec

Map 输出结果也以 Gzip 进行压缩:

## 启用map端输出压缩
set mapred.map.output.compress=true
## 默认值是org.apache.hadoop.io.compress.DefaultCodec
set mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.GzipCodec

对 Hive 输出结果和中间都进行压缩:

set hive.exec.compress.output=true  ## 默认值是false,不压缩
set hive.exec.compress.intermediate=true   ## 默认值是false,为true时MR设置的压缩才启用

二、HQL 语法和运行参数层面

2.1 查看 Hive 执行计划

需要了解具体的转换过程,可以在 SQL 语句中输入如下命令查看具体的执行计划

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

2.2 列裁剪和分区裁剪

这其实就是查询时只读取需要的列,分区裁剪就是只读取需要的分区。所以尽量不要 select * ,还有就是要指定分区

Hive 在读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值