由于 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.cnameOR t.area2 =c.cnameOR 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.cnameOR t.area2 =c.cnameOR 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 cidFROM tmpdb.city cJOIN ecdata.ext_trackflow t ON t.area1 =c.cnameWHERE t.statdate>='20140818'AND t.statdate<='20140824'AND platform='pc'UNION ALL SELECT t.statdate dt,c.cname name,t.cookieid cidFROM tmpdb.city cJOIN ecdata.ext_trackflow t ON t.area2 =c.cnameWHERE t.statdate>='20140818'AND t.statdate<='20140824'AND platform='pc'UNION ALL SELECT t.statdate dt,c.cname name,t.cookieid cidFROM tmpdb.city cJOIN ecdata.ext_trackflow t ON t.area3 =c.cnameWHERE 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 cidFROM tmpdb.city cJOIN ecdata.ext_trackflow t ON t.area1 =c.cnameWHERE t.statdate>='20140818'AND t.statdate<='20140824'AND platform='pc'UNION ALL SELECT /*+ MAPJOIN(c) */ t.statdate dt,c.cname name,t.cookieid cidFROM tmpdb.city cJOIN ecdata.ext_trackflow t ON t.area2 =c.cnameWHERE t.statdate>='20140818'AND t.statdate<='20140824'AND platform='pc'UNION ALL SELECT /*+ MAPJOIN(c) */ t.statdate dt,c.cname name,t.cookieid cidFROM tmpdb.city cJOIN ecdata.ext_trackflow t ON t.area3 =c.cnameWHERE 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 stageStage-1 depends on stages: Stage-11Stage-2 depends on stages: Stage-1Stage-3 depends on stages: Stage-2, Stage-6, Stage-9Stage-12 is a root stageStage-5 depends on stages: Stage-12Stage-6 depends on stages: Stage-5Stage-13 is a root stageStage-8 depends on stages: Stage-13Stage-9 depends on stages: Stage-8Stage-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 cidFROM tmpdb.city cJOIN ecdata.ext_trackflow t ON t.area1 =c.cnameWHERE t.statdate>='20140818'AND t.statdate<='20140824'
     AND platform='pc'UNION ALL SELECT /*+ MAPJOIN(c) */ t.statdate dt,c.cname name,t.cookieid cidFROM tmpdb.city cJOIN ecdata.ext_trackflow t ON t.area2 =c.cnameWHERE t.statdate>='20140818'AND t.statdate<='20140824'
     AND platform='pc'UNION ALL SELECT /*+ MAPJOIN(c) */ t.statdate dt,c.cname name,t.cookieid cidFROM tmpdb.city cJOIN ecdata.ext_trackflow t ON t.area3 =c.cnameWHERE 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 倍左右,最终 10min 出结果。

7、最后的问题:

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

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

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

8、关于 hive 中的 笛卡尔集( full Cartesian product )

在JION接连查询中没有ON连接key,而通过WHERE条件语句会产生笛卡尔集。
Hive本身是不支持笛卡尔集的,不能用select T1., T2. from table1, table2这种语法。但有时候确实需要用到笛卡尔集的时候,可以用下面的语法来实现同样的效果:
select T1., T2. from table1 T1 join table2 T2 where 1=1;
注意在Hive的Strict模式下不能用这种语法,因为这样会产生笛卡尔集,而这种模式禁止产生笛卡尔集。需要先用set hive.mapred.mode=nonstrict;设为非strict模式就可以用了,或者将where改为on连接。
select T1., T2. from table1 T1 join table2 T2 on T1.id=T2.id;

9、关于Strict Mode

Hive中的严格模式可以防止用户发出(可以有问题)的查询无意中造成不良的影响。 将hive.mapred.mode设置成strict可以禁止三种类型的查询:
1)、在一个分区表上,如果没有在WHERE条件中指明具体的分区,那么这是不允许的,换句话说,不允许在分区表上全表扫描。这种限制的原因是分区表通常会持非常大的数据集并且可能数据增长迅速,对这样的一个大表做全表扫描会消耗大量资源,必须要再WHERE过滤条件中具体指明分区才可以执行成功的查询。
2)、第二种是禁止执行有ORDER BY的排序要求但没有LIMIT语句的HiveQL查询。因为ORDER BY全局查询会导致有一个单一的reducer对所有的查询结果排序,如果对大数据集做排序,这将导致不可预期的执行时间,必须要加上limit条件才可以执行成功的查询。
3)、第三种是禁止产生笛卡尔集。在JION接连查询中没有ON连接key而通过WHERE条件语句会产生笛卡尔集,需要改为JOIN…ON语句。
10、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

[8] Hive连接产生笛卡尔集

http://blog.javachen.com/2013/10/17/cartesian-product-in-hive-inner-join/#

Hive join 优化实战相关推荐

  1. hive分桶表join_Hive:JOIN及JOIN优化 2015.10.25

    1. Join的基本原理 大家都知道,Hive会将所有的SQL查询转化为Map/Reduce作业运行于Hadoop集群之上.在这里简要介绍Hive将Join转化为Map/Reduce的基本原理(其它查 ...

  2. 【hive】数据倾斜-大表小表join优化mapjoin

    真正让你明白Hive调优系列3:笛卡尔乘积,小表join大表,Mapjoin等问题 0.Hive中的优化分类    真正想要掌握Hive的优化,要熟悉相关的MapReduce,Yarn,hdfs底层源 ...

  3. Hive SQL之FULL JOIN优化

    记一次工作中SQL 的FULL JOIN 优化过程 在完成同事交接的一个项目需求迭代的时候,发现了有一段Full Join的代码执行比较慢. 其代码大概如下: SELECT nvl(a.user_id ...

  4. Impala内存优化实战案例

    Impala内存优化实战案例 李珂 畅游DT时代 2016-03-25 文章来源:中国联通网研院网优网管部--IT技术研究团队 作者:李珂 一. 引言 Hadoop生态中的NoSQL数据分析三剑客Hi ...

  5. Hive基本操作,DDL操作(创建表,修改表,显示命令),DML操作(Load Insert Select),Hive Join,Hive Shell参数(内置运算符、内置函数)等

    1.  Hive基本操作 1.1DDL操作 1.1.1    创建表 建表语法 CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name [(col_nam ...

  6. 2 周流量激增百倍的腾讯课堂后台扩容和性能优化实战

    作者:andyawang,腾讯 CSIG 后台开发工程师 疫情期间,学校网课需求激增,腾讯课堂 2 天上线极速版,2 周内支持同时在线人数超百倍增长,对整个后台挑战非常大.整整 2 个月下来,同合作团 ...

  7. left join 索引失效无条件_技术分享 | MySQL 优化:JOIN 优化实践

    近期刚好学习了丁奇老师的<MySQL 实战 45 讲>中的 join 优化相关知识,又刚刚好碰上了一个非常切合的 join 查询需要优化,分析过程有些曲折,记录下来留作笔记.问题 SQL ...

  8. Hive JOIN使用详解

    Hive是基于Hadoop平台的,它提供了类似SQL一样的查询语言HQL.有了Hive,如果使用过SQL语言,并且不理解Hadoop MapReduce运行原理,也就无法通过编程来实现MR,但是你仍然 ...

  9. hive性能优化指南

    1.概述 继续<hive性能优化指南--初级篇>一文中的剩余部分,本篇博客赘述了在工作中总结Hive的常用优化手段和在工作中使用Hive出现的问题.下面开始本篇文章的优化介绍. 2.介绍 ...

最新文章

  1. 机器视觉系统原理及学习策略
  2. 创始人爆料!被谷歌收购前,DeepMind 已濒临破产
  3. Kotlin实战指南十九:use 函数魔法
  4. Xtreme8.0 - Kabloom dp
  5. Dynamic Data Web Application编译是报GetActionPath调用模糊解决办法
  6. [转]CentOS 7忘记root密码解决办法
  7. C语言extern关键词—最会带帽子的关键字
  8. DOCKER windows 7 详细安装教程
  9. 学生管理系统(简易)7/26
  10. 推荐时代的内容理解技术探索.pdf(附下载链接)
  11. 封装微信分享到朋友/朋友圈js
  12. 【Programming Clip】点分十进制IP和长整型转换
  13. WebBrowser自动点击链接 广告自动点击 Ads Auto Click
  14. 关于本学期西南交通大学ACM-ICPC校集训队 训练计划(Beta 1.0)
  15. tortoisegit 还原到某个版本
  16. SSH 命令的11种用法
  17. java application.doevents_Application.DoEvents的用法
  18. 一文看懂外汇风险准备金率调整为 20%的含义
  19. ubuntu 日常使用问题记录
  20. 基于云端的生命检测系统(合泰杯比赛报告内含代码)

热门文章

  1. STM32F103 TFTLCD显示实验(一)
  2. 纱线捻度、捻向和捻系数怎么选择?
  3. 儿童节,妈妈想对你说-----
  4. 三分钟了解服务架构演进及优缺点
  5. mysql delete语句非常耗时_解决项目中MySQL数据库执行删除语句时间太长的问题
  6. word域的使用方法
  7. 图形处理 柔化和锐化处理
  8. Week11手写笔记
  9. MongoDB数据日期显示相差8小时 原因和解决方案
  10. Telegram 汉化