hive 优化

Join 连接优化

普通的Join操作的Reduce 阶段,位于 Join左边的表的内容会被加载进内存,所以最好将小表放在左边。不过如果使用关键字/*+streamtable(大表名称)*/就无所谓位置了。

对于HiveQL,会先执行on条件筛选,再链接,在进行where筛选。On的筛选条件主要是针对从表,主表的数据都会输出。因此对于主表无关数据很多时,可以先使用子查询,过滤主表的无效数据。同时注意能用on filter的就不要用where

map side join

当小表关联一个超大表时,容易发生数据倾斜,可以用mapside join,把小表全部加载到内存在map端进行join,避免reducer处理。
SELECT /*+ MAPJOIN(user) */ l.session_id, u.username from user u join page_views l on (u. id=l.user_id) ;

hive0.7版本开始,设置

1
2
3
4
hive.auto.convert.join=true
hive.mapjoin.smalltable.filsize=25000000
--使用这个优化的小表的大小(单位:字节)
--注意:右外连接和全外连接不支持这个优化

可以自动判断能否mapside join

Count distinct

数据量小的时候无所谓,数据量大的情况下,由于COUNT DISTINCT操作需要用一个Reduce Task来完成,这一个Reduce需要处理的数据量太大,就会导致整个Job很难完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替换:

1
2
3
4
5
6
7
8
9
10
11
12
SELECT day,
COUNT(DISTINCT id) AS uv
FROM lxw1234
GROUP BY day
转化为
SELECT day,
COUNT(id) AS uv
FROM (
SELECT day,id
FROM lxw1234
GROUP BY day,id) a
GROUP BY day;

合理使用union all

http://superlxw1234.iteye.com/blog/1536440

group by数据倾斜

数据倾斜聚合优化,设置参数hive.groupby.skewindata = true,当选项设定为 true,生成的查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。

using Partitions and Buckets

通过对table的指定列进行partation和buckets可以更迅速的进行搜索

hive config相关

map和reduce个数优化

http://www.csdn.net/article/2015-01-13/2823530

合并小文件

文件数目过多,会给 HDFS 带来压力,并且会影响处理效率,可以通过合并 Map 和 Reduce 的结果文件来消除这样的影响:

  • hive.merge.mapfiles = true是否和并 Map 输出文件,默认为 True
  • hive.merge.mapredfiles = false是否合并 Reduce 输出文件,默认为 False
  • hive.merge.size.per.task = 25610001000合并文件的大小

并行执行

Hive引擎会将一个HiveQL查询语句分解成几个执行阶段(stages)(可以通过EXPLAIN HiveQL看出),默认情况下,Hive会一次执行一个阶段(stage),有时候一个包含多个执行阶段(stages)的HiveQL的stages之间并没有前后执行的依赖顺序,这种情况下将这些stages并行执行是一个很好的选择,可以带来更好的性能。
将hive.exec.parallel参数设置为true就会激活并行执行的功能,如果一个HiveQL作业可以并行的执行其多个stages,这就会提升集群的利用率:

1
2
3
4
5
<property>
<name>hive.exec.parallel</name>
<value>true</value>
<description>Whether to execute jobs in parallel</description>
</property>

jvm重用

JVM重用是Hadoop的一个性能调整的参数,它也会对Hive产生非常大的影响,特别是在很那避免处理大量小文件的场景中,每一个task执行方式景都很短,要知道默认新情况下每处理一个task都要启动一个JVM进程,JVM进程是一个重量级的进程,这就需要大量的资源的开销,这种情况下使用JVM重用可以大量减少这些不必要的JVM的初始化和销毁的开销,大大缩短总的执行时间。
这个参数可以再$HADOOP_HOME/conf/mapred-site.xml中设置:

1
2
3
4
5
6
7
<property>
<name>mapred.job.reuse.jvm.num.tasks</name>
<value>10</value>
<description>
How many tasks to run per jvm.if set to -1,there is no limit.
</description>
</property>

参考文献


本文采用创作共用保留署名-非商业-禁止演绎4.0国际许可证,欢迎转载,但转载请注明来自http://thousandhu.github.io,并保持转载后文章内容的完整。本人保留所有版权相关权利。

本文链接:http://thousandhu.github.io/2015/12/18/hive-优化/