在项目开发过程中,使用hive进行数据处理和分析的时候经常会出现问题,如:GC,数据倾斜,这些都是老生常谈的问题了,下面概括几个常用的hive调优方法

Hive调优

1)map端join

1)如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成CommonJoin,即:在Reduce阶段完成join。
容易发生数据倾斜。可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理。
2)set  hive.auto.convert.join=true;

2)行列过滤

行处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT*
列处理:表关联的时候,先在on前面加上过滤条件,这样会先过滤再关联表;如果在where后面加过滤条件,会先全表关联再过滤

3)使用Tez计算引擎

命令行:set hive.execution.engine=tez;
修改配置文件

4)采用分区、分桶技术

但少用动态分区

5)并行度优化

1)调整map数量
	增加map数量的情况:任务产生的小文件大小接近块大小,但是文件的结构非常简单,只有一个或两个字段,却有上千万条的数据,如果map数量过少,每个map处理的逻辑又非常复杂的话,这也非常耗时。这时需要适当增加map数量去分担压力
	
	减少map数量的情况:任务产生小文件过多,每个小文件大小远小于块大小(128M),每个小文件消耗一个map,map的启动和初始化时间远大于map的逻辑处理时间,这样非常消耗性能,浪费资源

2)调整reduce数量
	通过修改参数手动设置reduce数量
	根据数据量大小合理设置reduce数量

扩展:
	mapTask数量由split切片决定,这里mapTask数量指的就是map数量:
	1)文件大小小于128M(默认块大小),有多少个文件就有多少个mapTask
	2)文件大小大于128M,根据切分规则,有多少个切分就有多少个mapTask
	3)根据切片规则计算map数量的Hadoop中map源码公式:
	computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M
	(默认切片大小blockSize是128M,minSize大小默认是1M,maxSize默认>128M)

6)小文件问题

1)小文件合并:
	map端开启combiner: set hive.map.aggr = true
	合并map端输出文件:  hive.merge.mapfiles = true
	合并reduce端输出文件:hive.merge.mapredfiles = true

2)存储格式:
	Sequencefile存储格式代替默认的textfile存储格式一定程度上可以减少小文件

7)存储格式、压缩格式

   1)般企业里使用ORC或者Parquet,因为是列式存储,且压缩比非常高,查询速度快,占用硬盘空间少

   2)ORCfile存储格式可以提高join查询速度

8)减少count(distinct)

使用distinct容易造成数据倾斜,因为用了distinct就无法在map端进行combiner操作,可能会导致reduce端拉取数据计算的时候因处理逻辑过于复杂、数据量过大而遇到瓶颈

9)设置本地模式、并行模式、严格模式

本地模式:set hive.exec.mode.local.auto=true;默认为false

并行模式:set hive.exec.parallel=true;              //打开任务并行执行
		 set hive.exec.parallel.thread.number=16;  //同一个sql允许最大并行度,默认为8。

严格模式:hive的严格模式可以防止用户执行哪些可能产生不好影响的查询

  开启严格模式需要将hive.mapred.mode的值从默认的nonstrict,修改为strict

  开启严格模式会禁止以下操作:

   1)限制笛卡尔积的查询

   2)对于使用了order by语句的查询,后面必须接limit语句,防止处理排序的那个reducer执行时间过长

   3)对于分区表,需要加上where 分区字段,不允许用户扫描全表,不允许扫描所有分区

10)开启JVM重用
在实际生产环境一般都会开启JVM重用

当小文件过多或者task特别多的时候,Hadoop默认配置通常是派生JVM来执行map和Reduce任务,一个task伴随一次JVM的启动和销毁,当一个job中包含成百上千个task任务时,JVM重用可以使得JVM实例在同一个job中重复使用n次,n的值在mapred-site.xml文件中配置。

<property>
  <name>mapreduce.job.jvm.numtasks</name>
  <value>10</value>
  <description>通常在10-20之间,设定为-1表示无论task有多少个都重用一个JVM实例。</description>
</property>