Hive优化,
Hive优化
1.列裁剪:列裁剪的设置为hive.optimize.cp,默认为true
2.分区裁剪:分区裁剪的配置为hive.optimize.pruner,默认为true
3.join:对于一条语句中有多个join的情况,当join的条件相同时,即使有多张表,都会合并为一个MapReduce,并不是多个MapReduce。
如果join的条件不相同,MapReduce的任务数目和join操作的数据是对应的;
在使用写有join操作的查询语句时,由于在join操作的Reduce阶段,join执行时会将join操作符左边的表的内容加载进内存,所以写语句时应将条目少的表/子查询放在join操作符的左边,这样可以有效减少内存溢出错误的几率。
4.MapJoin:MapJoin的合理使用同样能起到调优的效果。在实际的应用中有可能遇到join执行效率很低甚至不能执行的状况。
例如,需要做不等值join,或者在join时有一个表极小。由于MapJoin会把小表全部读入内存中,Join操作在Map阶段完成,在Map阶段直接将另外一个表的数据和内存中表数据做匹配,所以不会对任务进行速度产生很大影响。即使笛卡尔积也是如此。
5.Group By优化:Map端局部聚合
众所周知,MapReduce计算框架中Reduce起到聚合操作的作用,但并不是所有的聚合操作都需要在Reduce端完成,很多聚合操作可以先在Map端进行局部聚合,最后在Reduce端做全局聚合得出最终结果。是否在Map端进行聚合由hive.map.agger控制,默认为True
而hive.groupby.mapagger.checkinterval用于控制在Map端进行聚合操作的条目数目,默认为100000。
优化常用手段
- 解决数据倾斜问题
- 减少job数
- 设置合理的map reduce的task数,能有效提升性能。
- 了解数据分布,自己动手解决数据倾斜问题是个不错的选择
- 数据量较大的情况下,慎用count(distinct)。
- 对小文件进行合并,是行至有效的提高调度效率的方法。
- 优化时把握整体,单个作业最优不如整体最优
数据类型方面的优化
合理的设置Buckets。在一些大数据join的情况下,map join有时候会内存不够。
如果使用Bucket Map Join的话,可以只把其中的一个bucket放到内存中,内存中原来放不下的内存表就变得可以放下。
这需要使用buckets的键进行join的条件连结,并且需要如下设置
set hive.optimize.bucketmapjoin = true
操作方面的优化
1.全排序
Hive的排序关键字是SORT BY,它有意区别于传统数据库的ORDER BY也是为了强调两者的区别–SORT BY只能在单机范围内排序 。
2.做笛卡尔积
当Hive设定为严格模式(hive.mapred.mode=strict)时,不允许在HQL语句中出现笛卡尔积
MapJoin是的解决办法,MapJoin,顾名思义,会在Map端完成Join操作。这需要将Join操作的一个或多个表完全读入内存
MapJoin的用法是在查询/子查询的SELECT关键字后面添加/*+ MAPJOIN(tablelist) */提示优化器转化为MapJoin(目前Hive的优化器不能自动优化MapJoin)
其中tablelist可以是一个表,或以逗号连接的表的列表。tablelist中的表将会读入内存,应该将小表写在这里
在大表和小表做笛卡尔积时,规避笛卡尔积的方法是,给Join添加一个Join key,原理很简单:将小表扩充一列join key,并将小表的条目复制数倍,join key各不相同;将大表扩充一列join key为随机数。
3.控制Hive的map数
4.决定reduce个数
Hadoop MapReduce程序中,reducer个数的设定极大影响执行效率。
不指定reducer个数的情况下,Hive会猜测确定一个reducer个数,基于以下两个设定:
参数1:hive.exec.reducers.bytes.per.reducer(默认为1G)
参数2 :hive.exec.reducers.max(默认为999)
5.合并mapreduce操作
Multi-group by
Multi-group by是Hive的一个非常好的特性,它使得Hive中利用中间结果变得非常方便。
FROM log
insert overwrite table test1 select log.id group by log.id
insert overwrite table test2 select log.name group by log.name
上述查询语句使用了Multi-group by特性连续group by了2次数据,使用不同的group by key。这一特性可以减少一次MapReduce操作。
Bucket和Sampling
Bucket是指将数据以指定列的值为key进行hash,hash到指定数目的桶中。这样就可以支持高效采样了。
Sampling可以在全体数据上进行采样,这样效率自然就低,它还是要去访问所有数据。而如果一个表已经对某一列制作了bucket,就可以采样所有桶中指定序号的某个桶,这就减少了访问量
如下例所示就是采样了test中32个桶中的第三个桶。
SELECT * FROM test 、、、TABLESAMPLE(BUCKET 3 OUT OF 32)
6.join原则
在使用写有 Join 操作的查询语句时有一条原则:应该将条目少的表/子查询放在 Join 操作符的左边。
原因是在 Join 操作的 Reduce 阶段,位于 Join 操作符左边的表的内容会被加载进内存,将条目少的表放在左边,可以有效减少发生 OOM 错误的几率。
map join Join操作在Map阶段完成,不再需要Reduce,前提条件是需要的数据在Map的过程中可以访问到。
7.group by
Map端部分聚合
并不是所有的聚合操作都需要在 Reduce 端完成,很多聚合操作都可以先在 Map 端进行部分聚合,最后在 Reduce 端得出最终结果基于 Hash。
8.合并小文件
文件数目过多,会给HDFS带来压力,并且会影响处理效率,可以通过合并Map和Reduce的结果文件来消除这样的影响。