Hive调优,
Hive调优
1、Fetch抓取(Hive可以避免进行mapreduce)
在hive中对于某些查询,并不需要使用mareduce计算,例如我们在select * from employee,在这种情况下,可以直接去employee的存储目录,然后输出查询结果到控制台。
在hive-default.xml.template文件中hive.fetch.task.conversion默认是more,老版本hive默认是minimal,该属性修改为more以后,在全局查找、字段查找、limit查找等都不走mapreduce。
set hive.fetch.task.conversion=more;
本地模式:
有时hive的输入数据量特别小,在查询时触发执行任务消耗的时间回避实际的job执行时间要多很多,在这种情况下,hive可以通过本地模式来在单台机器上处理所有的任务,在处理小数据集时,执行时间会大大缩短
用户可以设置hive.exec.mode.local.auto的值为true,来让hive在核实的时候自动启动这个优化。
2、表的优化
2.1join
join原则:
1)小表join大表
将key相对分散,并且数据量小的表放在join的左边,这样可以有效的减少内存溢出错误发生的概率,可以使用group让小的维度表(1000条以下的记录数)先进内存,在map端进行reduce。
select count(distinct s_id) from score;
#在map端进行聚合,效率更高
select count(s_id) from score group by s_id;
2)多表关联时,最好拆成小段,避免大sql(无法控制中间的job)
3)大表join小表
有时join超时是因为某些key对应的数据太多,而相同key对应的数据都会发送到相同的reducer上,从而导致内存不够。此时我们应该仔细分析这些异常的key,很多情况下,这些key对应的数据是异常数据,我们需要在SQL语句中进行过滤。我们可以通过hive的rand函数,随机的给每一个为空的id赋上一个随机值,这样就不会造成数据的倾斜。
2.2MapJoin
如果不指定MapJoin或者不符合MapJoin的条件,那么hive的解析器会将join操作转换成Common Join即,在reduce阶段完成join,容易发生数据倾斜,可以用MapJoi把小表的数据全部加载到内存中,在map端进行join,避免reduce处理。
#开启mapjoin参数设置
#设置自动选择mapjoin 默认为true
set hive.auto.convert.join = true;
#大表和小表的阈值设置(默认的25M以下为小表)
set hive.mapjoin.smalltable.filesize=25123456;
2.3 group by
默认情况下,Map阶段同一个Key数据发给同一个reduce,当一个key数据过大时就会出现数据倾斜,很多时候,并不是一定要在reduce阶段聚合,可以先在map阶段进行部分聚合,最后在reduce阶段得出最后的结果。
#设置map端参数聚合
set hive.map.aggr = true;
#设置在map端聚合操作的条目数
set hive.groupby.mapaggr.checkinterval = 100000;
#有数据倾斜时进行负载均衡(默认为false)
set hive.groupby.skewindata = true;
2.4Count(distinct)
在数据量小的时候,使用count无所谓,当数据量较大时,由于使用count来操作需要使用一个reducetask来完成,一个reduce需要处理的数据量太大了,就会导致整个Job难以完成,一般count distinct使用先group by 再 count的方式替换。
2.5笛卡尔积
在join时,避免使用笛卡尔积,不加on条件或者无效的on条件,hive只能使用一个reduce来完成笛卡尔积
3.数据倾斜
3.1map数
map数通常情况下,作业会通过input的目录产生一个或者多个map任务,当一个任务中有很多的小文件,并且大小远小于块大小128M,则每个小文件都会有一个map任务来完成,这会造成资源的浪费,而当map任务较少,而处理逻辑非常复杂时,只用一个map任务来执行,显然也是不够的。
3.2 减少map数
小文件进行合并
3.3增加map 数
当input的文件都很大,任务逻辑复杂,map执行非常慢的时候,可以考虑增加Map数,来使得每个map处理的数据量减少,从而提高任务的执行效率。
3.4reduce数
调整reduce个数的方法
方法一:
#每个reduce默认的处理数据量为256M
hive.exec.reducers.bytes.per.reducer=256123456
#每个任务最大的reduce数,默认为1009
hive.exec.reducers.max=1009
方法二:
在在hadoop的mapred-default.xml文件中修改设置每个job的Reduce个数
set mapreduce.job.reduces = 15;
reduce个数并不是越多越好
1)过多的启动和初始化reduce也会消耗时间和资源;
2)另外,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
在设置reduce个数的时候也需要考虑这两个原则:处理大数据量利用合适的reduce数;使单个reduce任务处理数据量大小要合适
4.使用EXPLAIN(执行计划)
基本语法:
EXPLAIN [EXTENDED | DEPENDENCY | AUTHORIZATION] query
案例实操:
(1)查看下面这条语句的执行计划
hive (default)> explain select * from course;
hive (default)> explain select s_id ,avg(s_score) avgscore from score group by s_id;
(2)查看详细执行计划
hive (default)> explain extended select * from course;
hive (default)> explain extended select s_id ,avg(s_score) avgscore from score group by s_id;
5.并行执行
Hive会将一个查询转化成一个或者多个阶段。这样的阶段可以是MapReduce阶段、抽样阶段、合并阶段、limit阶段。或者Hive执行过程中可能需要的其他阶段。默认情况下,Hive一次只会执行一个阶段。不过,某个特定的job可能包含众多的阶段,而这些阶段可能并非完全互相依赖的,也就是说有些阶段是可以并行执行的,这样可能使得整个job的执行时间缩短。不过,如果有更多的阶段可以并行执行,那么job可能就越快完成。
通过设置参数hive.exec.parallel值为true,就可以开启并发执行。不过,在共享集群中,需要注意下,如果job中并行阶段增多,那么集群利用率就会增加。
set hive.exec.parallel=true; //打开任务并行执行
set hive.exec.parallel.thread.number=16; //同一个sql允许最大并行度,默认为8。