Hive的优化
Posted 蓝小冰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hive的优化相关的知识,希望对你有一定的参考价值。
# Hive的计算和存储
hive的计算完全依赖于MapReduce!
hive的存储完全依赖于HDFS
# Hive什么情况下可以避免进行MapReduce
1.本地模式下,即没有使用复合函数(count,sum,avg等)
select uid,pid from sogou_uid_pid limit 10;
2.查询语句中的过滤条件是分区字段的情况下不会执行MapReduce。
# Hive的数据倾斜
数据倾斜的表现:大部分的reduce任务已经完成,少数的reduce一直停留在某个百分比不动。
数据倾斜的原因:
1).null值过多
2).key值分布不均匀
3).业务数据本身的问题
4).建表时考虑不周
解决办法:
会在下面的优化中详细的解释
# Hive的优化
## 0.使用explain
hive > explain select count(uid) from tmall_201412;
查询语句本身并不会被执行,他会以语法树的形式将执行过程展现出来。
## 1.join优化
如果join中的多个表的join key是同一个,则join会被转换为单个的map/reduce任务:
join时,Hive会缓存join序列中除了最后一个表的所有记录,在通过最后一个表将结果序列化到文件系统,这一实现有助于reduce端减少内存的使用量。生产中,应该把最大的表写在最后(否则会因为缓存浪费大量的内存)
## 2.本地模式
大多数的Hadoop的job需要Hadoop提供的完整的可扩展性来处理大数据集。不过有时候Hive的输入数据量是非常小的。在这样的情况下,查询也需要很长的时间才能完成。在大多数的情况下,Hive可以通过本地模式在单台机器上(或者某些时候在单个进程中)处理所有的任务。对于小数据集的执行时间会明显的缩短。
可以通过以下的命令,临时启动本地模式:
set oldjobtracker=${hiveconf:mapred.job.tracker};
set mapred.job.tracker=local;
set mapred.tmp.dir=/home/username/tmp;
set mapred.job.tracker=${oldjobtracker};
也可以通过修改配置文件(hive-site.xml),让Hive在适当的时候启动本地模式:
<property>
<name>hive.exec.mode.local.auto</name>
<value>true</value>
<description>
let hive determine whether to run in local mode automatically
</description>
</property>
## 3.limit
limit语句我们也经常用到,不过,在很多情况下limit语句还是需要执行整个查询语句,然后返回部分结果。因为这种情况通常是浪费的,所以我们应该尽量的避免这样的情况。我们可以通过Hive的配置文件来控制,当使用limit语句时,对数据源进行抽样:
<property>
<name>hive.limit.optimize.enable</name>
<value>true</value>
<description>Wheather to enable to optimization to try a smaller subset of data for simple limit first . </description>
</property>
当我们设置了hive.limit.optimize.enable的值为true,还有两个参数可以控制这个操作,hive.limit.row.max.size和hive.limit.optimize.limit.file:
<property>
<name>hive.limit.row.max.size</name>
<value>100000</value>
<description>
when trying a smaller subset of data for simple limit ,how much size we need to guarantee each row to hive at least.
</description>
</property>
<property>
<name>hive.limit.optimize.limit.file</name>
<value>10</value>
<description>
when trying a smaller subset if data for sumple limit,maximum number if files we can sample.
</description>
</property>
使用limit的优缺点:
缺点:有些需要的数据可能永远不会被处理到,
缺陷:有些数据始终得不到使用。
## 4.并行执行
Hive会将一个查询转换成一个或者多个stage。默认情况下,Hive一次只会执行一个stage。但是在某些job中可能包含众多的stage,而这些stage可能并非完全互相依赖,也就是说某些stage可以并行执行,这样可以使整个job的执行时间缩短,若很多stage都可以并行执行,那么集群的利用率就会增加,job的执行速度也会更快点。
我们可以通过配置文件,来开启并行执行
<property>
<name>hive.exec.parallel</name>
<value>true</value>
<description>
whether to execute jobs in parallel
</description>
</property>
## 5.严格模式
Hive提供了一个严格模式,以防止用户进行一些意想不到的不好的查询:
1).分区表查询的时候,没有where条件,不允许扫描所有的分区;
2).使用order by,必须使用limit 限制,可以防止reduce额外执行时间;
3).笛卡尔积,查询条件必须使用on 不能使用where替代。
## 6.JVM重用
MapReduce会将一个job转换成多个task。默认情况下,每一个task对应一个新的JVM实例,都需要开启和销毁的开销。对于小文件,每个文件都对应一个task。在一些情况下,JVM的开启和销毁可能会比实际处理数据的时间消耗要长!
JVM调优是Hadoop调优参数的内容,其对Hive的性能具有非常大的影响,特别是对于很难避免小文件的场景或者task特别多的场景,这类场景大多数的执行时间都很短。
Hadoop的默认配置通常是使用派生JVM来执行map和reduce任务。这时JVM的启动过程可能造成相当大的开销,尤其是执行的job包含成百上千个task任务的情况。JVM重用可以使得JVM实例在同一个job中重新使用N次。N的值可以在Hadoop的mapred-site.xml文件中设置:
<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>
缺点:开启JVM便会一直占用task插槽,以便进行重用,直到任务完成后才释放。如果某个后者某几个reduce任务执行时间比其他的reduce时间长的多的话,保留的插槽就会一直处于空闲的状态,无法被其他job使用,直到所有task都结束才会释放。
## 7.调整map和reduce的个数
Hive通过将查询划分成一个或者多个MapReduce任务达到并行执行的目的。每个任务都可能有多个mapper和reducer任务,其中至少有一些是可以并行执行的。
如果太多的mapper和reducer任务,就会导致启动阶段、调度和运行job过程产生过多的开销;若设置的数据量太少,就可能没有充分的利用集群内在的并行性。所以要根据具体的查询调整reduce的数目。
Hive是按照输入数据量大小来确定reducer个数的。我们可以通过dfs -count 命令来计算输入量的大小,这个命令和Linux中的du -s类似;用于计算指定目录下所有数据的总大小:
hdfs dfs -ls /cars
1 1 20671380 /cars
du -s ./data50W.dat
64772 ./data50W.dat
属性hive.exec.reducers.bytes.per.reducer的默认值是1GB。若Hive操作的输入数据量经过map之后产生了很大的数据量,这时reduce的数量计算就会影响执行,可以根据实际情况来动态的调整reduce处理的数据量。集群默认的reducer的个数为3个。
## 8.动态分区调整
可以调整动态分区插入允许的分区数。虽然太多的分区可能产生过多的小文件,造成NameNode负荷变重,但是还是将其设置大以便查询。
通过修改hive-site.xml调整:
设置动态分区的模式
<property>
<name>hive.exec.dynamic.partition.mode</name>
<value>strict</value>
<description>
in strict mode ,the user must specify at least one static partition in case the user accidentally overwrites all partitions .
</description>
</property>
<property>
<name>hive.exec.max.dynamic.partitions</name>
<value>300000</value>
<description>
maximum number of dynamic partitions allowed to be created in total .
</description>
</property>
设置最大的动态分区数
<property>
<name>hive.exec.max.dynamic.partitions.pernode</name>
<value>10000</value>
<description>
maxmum number of dynamic partitions allowed to be created in each mapper/reducer node.
</description>
</property>
## 9.map端的聚合以及muti-group by
事实上并不是所有的聚合操作都需要在reduce部分进行,很多聚合操作都可以先在map端进行部分的聚合,然后在reduce端得到最终结果。
## 10.推测执行
推测执行是Hadoop中的一个功能,可以触发执行一些重复的task。目标的通过加快获取单个task的结果以及进行侦测将执行慢的TaskTracker加入黑名单的方式来提高整体的任务执行效率。
若运行时的偏差非常敏感的话,那么可以将这些功能关掉,若输入的数据量很大,并且需要执行长时间的map或者reduce task的话,那么启动推测执行造成的浪费是非常大的。
Hive本身也提供了配置项来控制reduce-side的推测执行:
<property>
<name>hive.mapred.reduce.tasks.speculative.execution</name>
<value>true</value>
<description>
whether speculative execution for reducers should ve turned on.
</description>
</property>
## 11.压缩
减少数据的传输,达到加快速度的目的
以上是关于Hive的优化的主要内容,如果未能解决你的问题,请参考以下文章