一例 Hive join 优化实战

由于 hive 与传统关系型数据库面对的业务场景及底层技术架构都有着很大差异,因此,传统数据库领域的一些技能放到 Hive 中可能已不再适用。关于 hive 的优化与原理、应用的文章,前面也陆陆续续的介绍了一些,但大多都偏向理论层面,本文就介绍一个实例,从实例中一步步加深对 hive 调优的认识与意识。

1、需求

需求我做了简化,很简单,两张表做个 join,求指定城市,每天的 pv,用传统的 RDBMS SQL 写出来就这样的:

SELECT t.statdate,
       c.cname,
       count(t.cookieid)
FROM tmpdb.city c
JOIN ecdata.ext_trackflow t ON (t.area1= c.cname
                                OR t.area2 =c.cname
                                OR t.area3 = c.cname)
WHERE t.statdate>=‘20140818‘ and t.statdate<=‘20140824‘
  AND platform=‘pc‘
GROUP BY t.statdate,
         c.cname;

怎么样?根据 SQL 看懂需求没问题吧?

2、非等值 join 问题

然后把这条 SQL 贴到 hive 中去执行,然后你会发现报错了:

FAILED: SemanticException [Error 10019]: Line 5:32 OR not supported in JOIN currently ‘cname‘

这是因为 hive 受限于 MapReduce 算法模型,只支持 equi-joins(等值 join),要实现上述的非等值 join,你可以采用笛卡儿积( full Cartesian product )来实现:

SELECT t.statdate,
       c.cname,
       count(t.cookieid)
FROM tmpdb.city c
JOIN ecdata.ext_trackflow t
WHERE t.statdate>=‘20140818‘
  AND t.statdate<=‘20140824‘
  AND platform=‘pc‘
  AND (t.area1= c.cname
       OR t.area2 =c.cname
       OR t.area3 = c.cname)
GROUP BY t.statdate,
         c.cname;

然后再拿着这条语句执行下。

3、优化:reduce side join VS Cartesian product

如果你真的把这条语句放到 Hive 上执行,然后恰好你有张表还非常大,那么恭喜你。。。集群管理员估计会找你的麻烦了。。。

友情提示:笛卡儿积这种语句在 Hive 下慎用,大数据场景下的 m * n 映射结果你懂的。。。对此,Hive 特意提供了一个环境变量:hive.mapred.mode=strict; 防止笛卡儿积的执行:

FAILED: SemanticException [Error 10052]: In strict mode, cartesian product is not allowed. If you really want to perform the operation, set hive.mapred.mode=nonstrict

从 2 中的观察得知我们在 on 后面跟 join 条件,走的是 reduce side join,如果你在 where 后跟则是走 Cartesian product,但是这里单条 sql 又没法实现 reduce side join,还有没有其它办法呢?

4、改写非等值 join:union all

既然不允许非等值 join,那我们换一下思路,多个子查询 union all,然后汇总:

SELECT dt,
       name,
       count(cid)
FROM
  (SELECT t.statdate dt,
          c.cname name,
          t.cookieid cid
   FROM tmpdb.city c
   JOIN ecdata.ext_trackflow t ON t.area1 =c.cname
   WHERE t.statdate>=‘20140818‘
     AND t.statdate<=‘20140824‘
     AND platform=‘pc‘
   UNION ALL SELECT t.statdate dt,
                    c.cname name,
                    t.cookieid cid
   FROM tmpdb.city c
   JOIN ecdata.ext_trackflow t ON t.area2 =c.cname
   WHERE t.statdate>=‘20140818‘
     AND t.statdate<=‘20140824‘
     AND platform=‘pc‘
   UNION ALL SELECT t.statdate dt,
                    c.cname name,
                    t.cookieid cid
   FROM tmpdb.city c
   JOIN ecdata.ext_trackflow t ON t.area3 =c.cname
   WHERE t.statdate>=‘20140818‘
     AND t.statdate<=‘20140824‘
     AND platform=‘pc‘) tmp_trackflow
GROUP BY dt,
         name;

5、优化:map side join

上述语句走的是 reduce side join,从我们的需求及业务得知,tmpdb.city 是一张字典表,数据量很小,因此我们可以试试把上述的语句改写成 mapjoin:

SELECT dt,
       name,
       count(cid)
FROM
  (SELECT /*+ MAPJOIN(c) */ t.statdate dt,
                            c.cname name,
                            t.cookieid cid
   FROM tmpdb.city c
   JOIN ecdata.ext_trackflow t ON t.area1 =c.cname
   WHERE t.statdate>=‘20140818‘
     AND t.statdate<=‘20140824‘
     AND platform=‘pc‘
   UNION ALL SELECT /*+ MAPJOIN(c) */ t.statdate dt,
                                      c.cname name,
                                      t.cookieid cid
   FROM tmpdb.city c
   JOIN ecdata.ext_trackflow t ON t.area2 =c.cname
   WHERE t.statdate>=‘20140818‘
     AND t.statdate<=‘20140824‘
     AND platform=‘pc‘
   UNION ALL SELECT /*+ MAPJOIN(c) */ t.statdate dt,
                                      c.cname name,
                                      t.cookieid cid
   FROM tmpdb.city c
   JOIN ecdata.ext_trackflow t ON t.area3 =c.cname
   WHERE t.statdate>=‘20140818‘
     AND t.statdate<=‘20140824‘
     AND platform=‘pc‘) tmp_trackflow
GROUP BY dt,
         name;

6、优化无极限:开启 parallel 和 控制 reduce 个数

上述语句执行时,你可以看到执行计划和状态信息,以及结合你的 union all 语句可知,三个 union 语句之间没有依赖关系,其实是可以并行执行的:

explain SQL...
...
STAGE DEPENDENCIES:
  Stage-11 is a root stage
  Stage-1 depends on stages: Stage-11
  Stage-2 depends on stages: Stage-1
  Stage-3 depends on stages: Stage-2, Stage-6, Stage-9
  Stage-12 is a root stage
  Stage-5 depends on stages: Stage-12
  Stage-6 depends on stages: Stage-5
  Stage-13 is a root stage
  Stage-8 depends on stages: Stage-13
  Stage-9 depends on stages: Stage-8
  Stage-0 is a root stage
...

我们在 SQL 前加上如下环境变量选项:

set mapred.reduce.tasks=60;
set hive.exec.parallel=true;

让执行计划中的 Stage-11、Stage-12、Stage-13 并行执行,并控制好 reduce task 个数。

完整的语句如下:

hive -e "
SET mapred.reduce.tasks=60;

SET hive.exec.parallel=TRUE;

SELECT dt,
       name,
       count(cid)
FROM
  (SELECT /*+ MAPJOIN(c) */ t.statdate dt,
                            c.cname name,
                            t.cookieid cid
   FROM tmpdb.city c
   JOIN ecdata.ext_trackflow t ON t.area1 =c.cname
   WHERE t.statdate>=‘20140818‘
     AND t.statdate<=‘20140824‘
     AND platform=‘pc‘
   UNION ALL SELECT /*+ MAPJOIN(c) */ t.statdate dt,
                                      c.cname name,
                                      t.cookieid cid
   FROM tmpdb.city c
   JOIN ecdata.ext_trackflow t ON t.area2 =c.cname
   WHERE t.statdate>=‘20140818‘
     AND t.statdate<=‘20140824‘
     AND platform=‘pc‘
   UNION ALL SELECT /*+ MAPJOIN(c) */ t.statdate dt,
                                      c.cname name,
                                      t.cookieid cid
   FROM tmpdb.city c
   JOIN ecdata.ext_trackflow t ON t.area3 =c.cname
   WHERE t.statdate>=‘20140818‘
     AND t.statdate<=‘20140824‘
     AND platform=‘pc‘) tmp_trackflow
GROUP BY dt,
         name;

" > a1.txt

最后的优化效果是:2 中的语句三个小时没出结果。。。5 比 4 快 8 倍左右,6 比 5 快 2 倍左右。

7、最后的问题:

在 6 的语句执行的时候你会发现,其扫描了 三遍 源文件。而 hive 本身是对 union all 的 join 做了优化的,当多个 union all 子查询同一张表时,只扫描一次源文件,但这里为什么会三个子查询各扫描一次呢?

可能是这里的 union all 子查询使用了 join 的缘故,导致 hive 的 union all 执行计划优化失效了。

关于这块怎么能优化成只扫描一次源文件,或者你有更好的优化方案,欢迎留言交流。

8、Refer:

[1] Hive Query- Joining two tables on three joining conditions with OR operator

http://stackoverflow.com/questions/16272804/hive-query-joining-two-tables-on-three-joining-conditions-with-or-operator

[2] LanguageManual JoinOptimization

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+JoinOptimization

[3] hive 执行计划

http://yychao.iteye.com/blog/1749562

[4] Hive SQL解析/执行计划生成流程分析

http://yanbohappy.sinaapp.com/?p=265

[5] 数据仓库中的SQL性能优化(Hive篇)

http://www.zihou.me/html/2014/02/12/9207.html

[6] Hive优化以及执行原理

http://www.smartcitychina.cn/upload/2014-01/14012015376829.pdf

[7] Hive作业优化总结

http://my.oschina.net/yangzhiyuan/blog/262910

时间: 2024-10-11 17:33:31

一例 Hive join 优化实战的相关文章

hive join 优化 --小表join大表

1.小.大表 join 在小表和大表进行join时,将小表放在前边,效率会高,hive会将小表进行缓存. 2.mapjoin 使用mapjoin将小表放入内存,在map端和大表逐一匹配,从而省去reduce. 例子: select /*+MAPJOIN(b)*/ a.a1,a.a2,b.b2 from tablea a JOIN tableb b ON a.a1=b.b1 在0.7版本后,也可以用配置来自动优化 set hive.auto.convert.join=true;

大数据开发实战:Hive优化实战3-大表join大表优化

5.大表join大表优化 如果Hive优化实战2中mapjoin中小表dim_seller很大呢?比如超过了1GB大小?这种就是大表join大表的问题.首先引入一个具体的问题场景,然后基于此介绍各自优化方案. 5.1.问题场景 问题场景如下: A表为一个汇总表,汇总的是卖家买家最近N天交易汇总信息,即对于每个卖家最近N天,其每个买家共成交了多少单,总金额是多少,假设N取90天,汇总值仅取成交单数.A表的字段有:buyer_id. seller_id.pay_cnt_90day. B表为卖家基本信

Hive调优实战

Hive优化总结 ---by 食人花 优化时,把hive sql当做map reduce程序来读,会有意想不到的惊喜. 理解hadoop的核心能力,是hive优化的根本.这是这一年来,项目组所有成员宝贵的经验总结.   长期观察hadoop处理数据的过程,有几个显著的特征: 1.不怕数据多,就怕数据倾斜. 2.对jobs数比较多的作业运行效率相对比较低,比如即使有几百行的表,如果多次关联多次汇总,产生十几个jobs,没半小时是跑不完的.map reduce作业初始化的时间是比较长的. 3.对su

Hive JOIN使用详解

转自http://shiyanjun.cn/archives/588.html Hive是基于Hadoop平台的,它提供了类似SQL一样的查询语言HQL.有了Hive,如果使用过SQL语言,并且不理解Hadoop MapReduce运行原理,也就无法通过编程来实现MR,但是你仍然可以很容易地编写出特定查询分析的HQL语句,通过使用类似SQL的语法,将HQL查询语句提交Hive系统执行查询分析,最终Hive会帮你转换成底层Hadoop能够理解的MR Job. 对于最基本的HQL查询我们不再累述,这

Hive ive优化 (important)

Hive ive优化 要点:优化时,把hive sql当做map reduce程序来读,会有意想不到的惊喜. 理解hadoop的核心能力,是hive优化的根本. 长期观察hadoop处理数据的过程,有几个显著的特征: 1.不怕数据多,就怕数据倾斜. 2.对jobs数比较多的作业运行效率相对比较低,比如即使有几百行的表,如果多次关联多次汇总,产生十几个jobs,没半小时是跑不完的.map reduce作业初始化的时间是比较长的. 3.对sum,count来说,不存在数据倾斜问题. 4.对count

Hive Join

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Joins LanguageManualJoins Join Syntax Hive支持下面的表join语法结构: join_table: table_reference JOIN table_factor[join_condition] | table_reference {LEFT|RIGHT|FULL} [OUTER]JOIN table_reference jo

Hive性能优化

架构层面优化: l  分表 l  合理利用中间结果集,避免查过就丢的资源浪费,减低Hadoop的IO负载 l  常用复杂或低效函数尽量不用或拆分成其他实现方式,如count(distinct) l  合理设计表分区,静态分区和动态分区 l  优化时一定要把握整体,单个作业最优不如整个作业最优. l  文件存储格式和压缩方式 l  Hadoop本身的优化 l  有些逻辑,使用系统函数可能比较复杂,可能涉及多层嵌套,建议使用自定义函数实现. 架构层面优化,我这里不做过多介绍了,写HQL时要时常考虑按

【转】Hive性能优化

1.概述 继续<那些年使用Hive踩过的坑>一文中的剩余部分,本篇博客赘述了在工作中总结Hive的常用优化手段和在工作中使用Hive出现的问题.下面开始本篇文章的优化介绍. 2.介绍 首先,我们来看看Hadoop的计算框架特性,在此特性下会衍生哪些问题? 数据量大不是问题,数据倾斜是个问题. jobs数比较多的作业运行效率相对比较低,比如即使有几百行的表,如果多次关联多次汇总,产生十几个jobs,耗时很长.原因是map reduce作业初始化的时间是比较长的. sum,count,max,mi

蚂蚁金服架构师带你深入性能优化一MySql性能优化实战

概要: Mysql的优化,大体可以分为三部分:索引的优化,sql语句的优化,表的优化.本文主要帮助自己整理思路,也可作为一个学习MySQL优化的提纲. 索引的优化 只要列中含有NULL值,就最好不要在此例设置索引,复合索引如果有NULL值,此列在使用时也不会使用索引 尽量使用短索引,如果可以,应该制定一个前缀长度 对于经常在where子句使用的列,最好设置索引,这样会加快查找速度 对于有多个列where或者order by子句的,应该建立复合索引 对于like语句,以%或者'-'开头的不会使用索