Hive Hive性能调优

最近慢慢把工作中涉及到的Hive知识和优化方法整理一下

一、Hive 的mapreduce

在实际业务中,我们使用的Hive通常是基于map reduce计算方式的。通俗的来讲,map负责映射或筛选关系(比如where,±等操作),reduce负责整合或这说规约操作(如group by,join等)。

通常我们要评估我们所写的hql性能,需要先知道所写hql的执行过程和mapredcue过程。此处引用一张网上的图片,很好的表示和mapreduce的过程:
Hive Hive性能调优_第1张图片
比如我们有如下的hql语句,我们一步一步开将其运行步骤拆分
Hive Hive性能调优_第2张图片
上面的hql语句有三个子查询没并且三个子查询的查询接通过通过id关联。

1.1.对于子查询1,由于其内存在over()函数,因此在执行会有reduce操作。具体的执行顺序为from->where->select->over,其中前三步都通过map实现,最后的over由reduce实现。
1.2.对于子查询2,内部没有聚合类的函数,因此不会执行reduce操作。具体的执行顺序为from->where->select,全部由map完成。
1.3.对于子查询3,内部有group by函数,因此会执行reduce操作。具体的执行顺序为from->where->select->group by,其中前三步都通过map实现,最后的gropu by由reduce实现。
2.得到子查询1、2、3的结果后,会先通过join关联查询1、2的结果,这是通过reduce完成的,得到结果后再通过join关联联查询3,这也是reduce完成的。
3.最后得到结果在通过group by得到最终结果,和前面一样,group by是通过reduce完成的。

通常来讲我们hql执行所花费的大部分时间都在shuffle+reduce的阶段(一些join和group by等操作),当数据倾斜时,这些操作会耗费极大的时间。

当然Hive还有一些其他运行方式(比如Tez,大概就是吧map和reduce继续拆分,关于这些本人也没有特别深入的研究)。

二、Hive各阶段容易出现的问题

Hive在map阶段和reduce阶段在hql使用不当时都会出现问题。总的来讲reduce阶段比map阶段更容易出现问题。

1.map阶段问题和办法

1.1.数据量过大
数据量太大时,集群资源会非常紧张。此时要注意Hive建表尽量要合理分区(每个分区数据都在不同文件内)

1.2.取数逻辑过于复杂
当hql中用到比较复杂的逻辑时,比如使用分复杂正则匹配regexp或过长的case when等语句也会导致提取效率低下。我们再写hql时可以尝试先用where筛选一道,避免全部数据都带入到复杂函数中。

2.reduce阶段问题

2.1.数据量过大
reduce数据量多大一方面是map时过滤出数据导致,因此能尽早过滤掉数据就尽早过滤掉数据。
另一方面,数据倾斜也会让reduce效率低下(一般来说reducers卡在一个位置很久,大概率就是发生了数据倾斜)。我们最好剔除掉导致倾斜的key,如果必须要使用,可尝试对数据倾斜的key打散(比如在key后面加上一个随机整数)

2.2.笛卡尔积
再关联时,如果关联的字段存在多对多的关系,就会产生笛卡尔积。笛卡尔积对于运行效率影响是十分致命的
为了防止笛卡尔积,我们需要保证两个表join时,一个表关联的字段在表中的值每一行都是唯一的(比如主键)。还有在子查询中就要限制好分区(在子查询外限制分区,回先执行on,还是会导致笛卡尔积)。对于此类事件,一定要事前就进行调查和评估。

2.3.over等复杂函数的计算
over()一类的函数的复杂度是非常高的。如若我们使用over只是为了去最大、最小、总和等记录时,最好不要用over()函数,而直接使用max()、min()、sum()等配合group by使用。此外我们还要避免不必要的distinct、order by等语句。

当然,关于hql还有许多其他优化的小技巧,比如使用mapjoin(将关联的小表放在mapper的内存中,让join在map段就可以进行。但是好像现在的Hive版本好像普通的left join就能完成这样的操作?);当关联时,结果表不需要另一表的字段,可以不用join,直接用in或者left semi join;使用合理的函数减少reduce操作等。

你可能感兴趣的:(Hive)