hive性能调优

Posted Hadoop大数据之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hive性能调优相关的知识,希望对你有一定的参考价值。

Hadoop为海量数据存储和计算提供了一种能力,在Hadoop的计算框架特性下会衍生如下问题:

1、数据量大不是问题,数据倾斜是个问题;

2、jobs数比较多的作业运行效率较低,原因是map reduce作业初始化的时间比较长;

3、count(distinct)在数据量大的情况下,效率极低,如果是多count(distinct)效率更低,因为count(distinct)是按group by字段分组,按distinct字段排序,一般这种分布方式是很倾斜的。

面对这些问题,有哪些有效的优化手段呢?


一、行/列式存储特点


行式存储

优点:

相关的数据是保存在一起的,比较符合面向对象的思维,因为一行数据就是一条记录;这种存储格式比较方便进行INSERT/UPDATE操作。

缺点:

如果查询涉及某几列,它会把整行数据读取出来,不能跳过不必要的列读取,如果数据量比较大就比较影响性能;如果每一行中,列的数据类型不一致,导致不容易获得一个极高的压缩比,导致空间利用率不高;不是所有的列都适合作为索引。

列式存储

优点:

查询数据时,只有涉及的列才会被查询,不会把所有列查询出来,即可以跳过不必要的列查询;高效的压缩率,节省存储空间和计算内存CPU;任何列都可以作为索引。

缺点:

INSERT/UPDATE不方便;不适合扫描小量的数据。


二、hive文件存储格式

1、textfile

默认存储格式,存储方式:行存储。特点:磁盘开销大,数据解释开销大,压缩的text文件hive无法进行合并和拆分。

2、sequencefile

二进制文件,以<key, value>的形式序列化到文件中,存储方式:行存储。特点:可分割,可压缩,与hadoop的mapfile是互相兼容的。

3、rcfile

存储方式:数据按行分块,每块按照列存储。特点:压缩快,快速列存取。

4、orc

存储方式:数据按行分块,每块按照列存储。特点:压缩快,快速列存取,效率比rcfile高,是rcfile的改良版本。

5、自定义格式

可以通过实现InputFormat和OutputFormat来自定义输入输出格式。


三、hadoop四种压缩格式

1、gzip压缩

优点:压缩率比较高,而且压缩/解压速度较快,hadoop本身支持,在应用中处理gzip格式的文件和直接处理文本一样。

缺点:不支持split。

应用场景:当每个文件压缩之后在1个块大小内,都可以考虑用gzip压缩格式。

2、lzo压缩

优点:压缩/解压速度较快,合理的压缩率,支持split,是hadoop中最流行的压缩格式,支持hadoop native库,可以在linux系统下安装lzop命令,使用方便。

缺点:压缩率比gzip要低一些,hadoop本身不支持,需要安装,在应用中对lzo格式的文件需要做一些特殊处理。

应用场景:一个很大的文本文件,压缩之后还大于一个块大小以上的可以考虑,而且单个文件越大,lzo优点越越明显。

3、snappy压缩

优点:高速压缩速度和合理的压缩率,支持hadoop native库。

缺点:不支持split,压缩率比gzip要低,hadoop本身不支持,需要安装,linux系统下没有对应的命令。

应用场景:当mapreduce作业的map输出的数据比较大的时候,作为map到reduce的中间数据的压缩格式;或者作为一个mapreduce作业的输出和另外一个mapreduce作业的输入。

4、bzip2压缩

优点:支持split,具有很高的压缩率,比gzip压缩率都高,hadoop本身支持,但不支持native,在linux系统下自带bzip2命令,使用方便。

缺点:压缩/解压速度慢,不支持native。

应用场景:适合对速度要求不高,但需要较高的压缩率的情况。

在hive中对中间数据或最终数据做压缩,是提高数据吞吐量和性能的一种手段。对数据做压缩,可以大量减少磁盘的存储空间,压缩后的文件在磁盘间传输和I/O也会大大减少,当然压缩和解压也会带来额外的CPU开销,但是却可以节省更多的I/O和使用更少的内存。数据压缩对I/O密集型作业带来大大的性能提升,如果作业是CPU密集型则会降低性能。


四、调优策略

1、JVM重用

JVM重用不是指同一Job的两个或两个以上的Task同时运行于同一JVM上,而是 N个Task按顺序在同一个Jvm上运行,即省去了Jvm关闭和再重启的时间。

N值可以在Hadoop的mapre-site.xml文件mapreduce.job.jvm.numtasks(默认1)属性进行设置,也可以通过set mapred.job.reuse.jvm.num.tasks=10设置;

2、并行执行

同时执行hive的多个阶段。hive在执行过程,将一个查询转化成一个或者多个阶段,而这些阶段可能并非完全相互依赖的,也就是说可以并行执行的,这样可能使得整个job的执行时间缩短hive执行开启:set hive.exec.parallel=true;

3、调整reduce数

参数1:hive.exec.reducers.bytes.per.reducer=256000000(每个reduce任务处理的数据量);参数2:hive.exec.reducers.max=1009(每个任务最大的reduce数目);计算公式:reducer个数=min(参数2,总输入数据量/参数1)。set mapred.reduce.tasks=N(每个任务默认的reduce数目),典型为0.99*reduce槽数,hive默认为-1,即自动确定reduce数目。reduce的个数设置其实对执行效率有很大的影响:1、如果reduce太少,如果数据量很大,会导致这个reduce异常的慢,从而导致这个任务不能结束,也有可能会OOM。2、如果reduce太多,产生的小文件太多,合并起来代价太高,namenode的内存占用也会增大。

4、调整map数

(1)默认map个数

如果不进行任何设置,默认的map个数是和blcok_size相关的。default_num = total_size / block_size

(2)期望大小

可以通过参数mapred.map.tasks来设置程序员期望的map个数,但是这个个数只有在大于default_num的时候,才会生效。

goal_num = mapred.map.tasks

(3)设置处理的文件大小

可以通过mapred.min.split.size 设置每个task处理的文件大小,但是这个大小只有在大于block_size的时候才会生效。

split_size = max(mapred.min.split.size, block_size)

split_num = total_size / split_size

(4)计算的map个数

compute_map_num = min(split_num,  max(default_num, goal_num))

除了这些配置以外,mapreduce还要遵循一些原则。 mapreduce的每一个map处理的数据是不能跨越文件的,也就是说min_map_num >= input_file_num。 所以,最终的map个数应该为:

final_map_num = max(compute_map_num, input_file_num)

结论:

1)如果想增加map个数,则设置mapred.map.tasks为一个较大的值。

2)如果想减小map个数,则设置mapred.min.split.size 为一个较大的值。

3)如果输入中有很多小文件,依然想减少map个数,则需要将小文件merger为大文件,然后使用准则2。

5、配置map输入合并

每个Map最大输入大小,决定合并后的文件数。

set mapred.max.split.size=256000000;

一个节点上split的至少的大小 ,决定了多个data node上的文件是否需要合并

set mapred.min.split.size.per.node=100000000;

一个交换机下split的至少的大小,决定了多个交换机上的文件是否需要合并

set mapred.min.split.size.per.rack=100000000;

执行Map前进行小文件合并

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; 

6、配置hive输出结果合并

hive.merge.mapfiles 在map-only job后合并文件,默认true

hive.merge.mapredfiles 在map-reduce job后合并文件,默认false

hive.merge.size.per.task 合并后每个文件的大小,默认256000000

hive.merge.smallfiles.avgsize 平均文件大小,是决定是否执行合并操作的阈值,默认16000000

hive性能调优参数(仅供参考):

#jvm重用

set mapred.job.reuse.jvm.num.tasks=10;

#并行执行

set hive.exec.parallel=true;

set hive.exec.parallel.thread.number=8;

#输出合并

set hive.merge.mapfiles=true;

set hive.merge.mapredfiles=true;

set hive.merge.size.per.task=256000000;

set hive.merge.smallfiles.avgsize=16000000;#输出文件的平均大小小于该值则启动一个独立的MR任务进行文件合并

#输入合并

set mapred.max.split.size=256000000; 

set mapred.min.split.size.per.node=256000000; 

set mapred.min.split.size.per.rack=256000000;

set hive.hadoop.supports.splittable.combineinputformat=true; 

set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; 

#输出压缩

set hive.exec.compress.output=true; 

set mapred.output.compress=true; 

set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec; 

set io.compression.codecs=org.apache.hadoop.io.compress.GzipCodec;  

以上是关于hive性能调优的主要内容,如果未能解决你的问题,请参考以下文章

Hive参数与性能企业级调优

Hive参数与性能企业级调优

Hive参数与性能企业级调优

Hive参数与性能企业级调优

Hive参数与性能企业级调优

Hive 查询性能调优