Hive 的优化

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/fengzheku/article/details/52300157
1、group by   实现 distinct

原始语句:
select count(distinct ip) 
from (select ip as ip from comprehensive.f_client_boot_daily where year="2013" and month="10"  
union all 
select pub_ip as ip from f_app_boot_daily where year="2013" and month="10" 
union all 
select ip as ip from format_log.format_pv1 where year="2013" and month="10" and url_first_id=1 
) d

原因:
select ip as ip from comprehensive.f_client_boot_daily where year="2013" and month="10"这个语句筛选出来的数据约有10亿条,select pub_ip as ip from f_app_boot_daily where year="2013" and month="10"约有10亿条条,select ip as ip from format_log.format_pv1 where year="2013" and month="10" and url_first_id=1 筛选出来的数据约有10亿条,总的数据量大约30亿条。这么大的数据量,使用disticnt函数,所有的数据只会shuffle到一个reducer上,导致reducer数据倾斜严重

优化后的语句:
select count(*) 
from 
(select ip 
from
(select ip as ip from comprehensive.f_client_boot_daily where year="2013" and month="10" 
union all 
select pub_ip as ip from f_app_boot_daily where year="2013" and month="10" 
union all 
select ip as ip from format_log.format_pv1 where year="2013" and month="10" and url_first_id=1
) d 
group by ip ) b

2、 join 优化:

生 成一个job:
多表连接,如果多个表中每个表都使用同一个列进行连接(出现在JOIN子句中),则只会生成一个MR Job,例如:
1 SELECT a.val, b.val, c.val FROM JOIN ON (a.key = b.key1) JOIN ON(c.key = b.key1)

三个表a、b、c都分别使用了同一个字段进行连接,亦即同一个字段同时出现在两个JOIN子句中,从而只生成一个MR Job。

生成多个job:

多表连接,如果多表中,其中存在一个表使用了至少2个字段进行连接(同一个表的至少2个列出现在JOIN子句中),则会至少生成2个MR Job,例如:

1 SELECT a.val, b.val, c.val FROM JOIN ON (a.key = b.key1) JOIN ON(c.key = b.key2)

三个表基于2个字段进行连接,这两个字段b.key1和b.key2同时出现在b表中。连接的过程是这样的:首先a和b表基于a.key和b.key1进行连接,对应着第一个MR Job;表a和b连接的结果,再和c进行连接,对应着第二个MR Job。
3、表连接顺序优化:
多表连接,数据量大的表放后面。
1 SELECT a.val, b.val, c.val FROM JOIN ON (a.key = b.key1) JOIN ON(c.key = b.key1)

这个JOIN语句,会生成一个MR Job,在选择JOIN顺序的时候,数据量相比应该是b < c,表a和b基于a.key = b.key1进行连接,得到的结果(基于a和b进行连接的Key)会在Reducer上缓存在buffer中,在与c进行连接时,从buffer中读取Key(a.key=b.key1)来与表c的c.key进行连接。
另外,也可以通过给出一些Hint信息来启发JOIN操作,这指定了将哪个表作为大表,从而得到优化。例如:

1 SELECT /*+ STREAMTABLE(a) */ a.val, b.val, c.val FROM JOIN ON(a.key = b.key1) JOIN ON (c.key = b.key1)
上述JOIN语句中,a表被视为大表,则首先会对表b和c进行JOIN,然后再将得到的结果与表a进行JOIN。

4、 基于条件的LEFT OUTER JOIN优化

左连接时,左表中出现的JOIN字段都保留,右表没有连接上的都为空。对于带WHERE条件的JOIN语句,例如:

1 SELECT a.val, b.val FROM LEFT OUTER JOIN ON (a.key=b.key)
2 WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'

执行顺序是,首先完成2表JOIN,然后再通过WHERE条件进行过滤,这样在JOIN过程中可能会输出大量结果,再对这些结果进行过滤,比较耗时。可以进行优化,将WHERE条件放在ON后,例如:

1 SELECT a.val, b.val FROM LEFT OUTER JOIN b
2 ON (a.key=b.key AND b.ds='2009-07-07' AND a.ds='2009-07-07')
这样,在JOIN的过程中,就对不满足条件的记录进行了预先过滤,可能会有更好的表现。

5、左半连接

左半连接(LEFT SEMI JOIN)

左半连接实现了类似IN/EXISTS的查询语义,使用关系数据库子查询的方式实现查询SQL,例如:

1 SELECT a.key, a.value FROM WHERE a.key IN (SELECT b.key FROM b);

使用Hive对应于如下语句:

1 SELECT a.key, a.val FROM LEFT SEMI JOIN ON (a.key = b.key)

需要注意的是,在LEFT SEMI JOIN中,表b只能出现在ON子句后面,不能够出现在SELECT和WHERE子句中。
关于子查询,这里提一下,Hive支持情况如下:

  • 在0.12版本,只支持FROM子句中的子查询;
  • 在0.13版本,也支持WHERE子句中的子查询。

6、

Map Side JOIN

Map Side JOIN优化的出发点是,Map任务输出后,不需要将数据拷贝到Reducer节点,降低的数据在网络节点之间传输的开销。
多表连接,如果只有一个表比较大,其他表都很小,则JOIN操作会转换成一个只包含Map的Job,例如:

1 SELECT /*+ MAPJOIN(b) */ a.key, a.value FROM JOIN ON a.key = b.key

对于表a数据的每一个Map,都能够完全读取表b的数据。这里,表a与b不允许执行FULL OUTER JOIN、RIGHT OUTER JOIN。 

猜你喜欢

转载自blog.csdn.net/fengzheku/article/details/52300157