Hive调优
Hive调优
1、文件调优
Hive支持的存储数据的格式主要有:TEXTFILE(行存储) 、SEQUENCEFILE(行存储) 、ORC(列存储) 、PARQUET(列存储) 。
textfile格式
Hive默认格式,数据不做压缩,磁盘开销大,数据解析开销大。可结合Gzip、Bzip2使用,但使用Gzip这种方式,hive不会对数据进行切分,从而无法对数据进行并行操作。
Orc格式
是Hive 0.11版里引入的新的存储格式。
Parquet格式
Parquet文件是以二进制方式存储的,所以是不可以直接读取的,文件中包括该文件的数据和元数据,因此Parquet格式文件是自解析的。
2、Fetch抓取
Hive中对某些情况的查询可以不必使用MapReduce计算。例如:SELECT * FROM employees;在这种情况下,Hive可以简单地读取employee对应的存储目录下的文件,然后输出查询结果到控制台。
在hive-default.xml.template
文件中hive.fetch.task.conversion
默认是more,老版本hive默认是minimal,该属性修改为more以后,在全局查找、字段查找、limit查找等都不走mapreduce。
3、本地模式
对于大多数这种情况,Hive可以通过本地模式在单台机器上处理所有的任务。对于小数据集,执行时间可以明显被缩短。
用户可以通过设置hive.exec.mode.local.auto
的值为true,来让Hive在适当的时候自动启动这个优化,默认是false。
1 | set hive.exec.mode.local.auto=true; //开启本地mr |
4、MapJoin
如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。容易发生数据倾斜。可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理。
1 | # 开启Mapjoin ,默认为true |
5、GroupBy
默认情况下,Map阶段同一Key数据分发给一个reduce,当一个key数据过大时就倾斜了。
并不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端进行部分聚合,最后在Reduce端得出最终结果。
1 | # 是否在Map端进行聚合,默认为True |
6、Count(Distinct) 去重统计
数据量小的时候无所谓,数据量大的情况下,由于COUNT DISTINCT的全聚合操作,即使设定了reduce task个数,set mapred.reduce.tasks=100
; hive也只会启动一个reducer。,这就造成一个Reduce处理的数据量太大,导致整个Job很难完成,一般COUNT DISTINCT使用先 GROUP BY再COUNT的方式替换:
7、避免笛卡尔积
尽量避免笛卡尔积,join的时候不加on条件,或者无效的on条件,Hive只能使用1个reducer来完成笛卡尔积。
8、行列过滤
列处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,**少用SELECT ** 。
行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤。 简单说就是子查询先写where条件过滤之后在关联查询。
9、动态分区调整
关系型数据库中,对分区表Insert数据时候,数据库自动会根据分区字段的值,将数据插入到相应的分区中,Hive中也提供了类似的机制,即动态分区(Dynamic Partition),只不过,使用Hive的动态分区,需要进行相应的配置。
1 | # 开启动态分区功能(默认true,开启) |
10、合理设置Map和Reduce数
调整Map数:
Map数量决定因素:input的文件总个数,input的文件大小,集群设置的文件块大小。
增加map的方法为:根据computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M
公式,调整maxSize最大值。让maxSize最大值低于blocksize就可以增加map的个数。
调整Reduce数:
过多的启动和初始化reduce也会消耗时间和资源;
另外,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
在设置reduce个数的时候也需要考虑这两个原则:处理大数据量利用合适的reduce数;使单个reduce任务处理数据量大小要合适;
1 | # 方法一 公式:N=min(参数2,总输入数据量/参数1) |
11、合并小文件
在map执行前合并小文件,减少map数:CombineHiveInputFormat具有对小文件进行合并的功能(系统默认的格式)。HiveInputFormat没有对小文件合并功能。
1
set hive.input.format= org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
在Map-Reduce的任务结束时合并小文件的设置:
1
2
3
4
5
6
7
8# 在map-only任务结束时合并小文件,默认true
SET hive.merge.mapfiles = true;
# 在map-reduce任务结束时合并小文件,默认false
SET hive.merge.mapredfiles = true;
# 合并文件的大小,默认256M
SET hive.merge.size.per.task = 268435456;
# 当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件merge
SET hive.merge.smallfiles.avgsize = 16777216;
11、并行执行
通过设置参数hive.exec.parallel值为true,就可以开启并发执行。不过,在共享集群中,需要注意下,如果job中并行阶段增多,那么集群利用率就会增加。当然,得是在系统资源比较空闲的时候才有优势,否则,没资源,并行也起不来。
1 | set hive.exec.parallel=true; //打开任务并行执行 |
12、严格模式
通过设置属性hive.mapred.mode
值为默认是非严格模式nonstrict 。开启严格模式需要修改hive.mapred.mode值为strict,开启严格模式可以禁止3种类型的查询。
- 对于分区表,除非where语句中含有分区字段过滤条件来限制范围,否则不允许执行。
- 对于使用了order by语句的查询,要求必须使用limit语句。
- 限制笛卡尔积的查询。
13、JVM重用
这个功能的缺点是,开启JVM重用将一直占用使用到的task插槽,以便进行重用,直到任务完成后才能释放。如果某个“不平衡的”job中有某几个reduce task执行的时间要比其他Reduce task消耗的时间多的多的话,那么保留的插槽就会一直空闲着却无法被其他的job使用,直到所有的task都结束了才会释放。
1 | <!--可以在Hadoop的mapred-site.xml文件中进行配置。通常在10-20之间。--> |
14、推测执行
设置开启推测执行参数:Hadoop的mapred-site.xml文件中进行配置,默认是true
1 | <property> |
Hive本身也可以设置
1 | <property> |