Hive.LEFT SEMI JOIN子句

7 篇文章 0 订阅

        公司的数据仓库和离线数据分析是建立在Hadoop + Hive基础上的,现在的工作主要是数据分析,自然也就跟HQL查询经常打交道了。刚来公司几乎完全不懂数据库知识,神马结构化查询语言也只是听说而已,不过,这没关系,实际工作一来,学习起来还是很快~~

        年前有一个同事叫帮忙查某个产品的月度留存UV这个数据,当时业务不熟,还去参照了一下别人是怎么定义留存用户这个指标的。。。然后根据自己的理解,用下面这种形式(其实刚开始的逻辑写得比这个还拙计,我不会到处乱说)的脚本逻辑去查:

SELECT
	t1.产品类型,
	COUNT(DISTINCT (IF(t2.用户ID IS NULL, NULL, t1.用户ID))) AS KEEP_UV
FROM
(
	SELECT
		产品类型,
		用户ID
	FROM 事实表
	WHERE (`DATE` >= 20140201 AND `DATE` <= 20140228)
) t1
LEFT OUTER JOIN
(
	SELECT
		产品类型,
		用户ID
	FROM 事实表
	WHERE (`DATE` >= 20140101 AND `DATE` <= 20140131)
) t2 ON (t1.产品类型 = t2.产品类型 AND t1.用户ID = t2.用户ID)
GROUP BY t1.产品类型

        

       但是,这个事实表本身所包含的字段很多,信息量很大,加上时间跨度为2个月,当时就想会不会略慢,结果跑起来果然慢得很,Map或者Reduce的任务经常卡在某个百分点比较久时间。

       看着MapReduce像蜗牛一样行进着,我才忽然想到在官方Wiki上貌似看到过这种 IN / EXISTS子查询(准确地说,这里是非相关子查询)有一种高效的实现,就是LEFT SEMI JOIN:

       LEFT SEMI JOIN implements the uncorrelated IN/EXISTS subquery semantics in an efficient way.

       于是抱着试一试的心态,马上修改脚本,用下面的形式去跑:

SELECT
	产品类型,
	COUNT(DISTINCT t1.用户ID) AS KEEP_UV
FROM
(
	SELECT
		产品类型,
		用户ID
	FROM 事实表
	WHERE (`DATE` >= 20140201 AND `DATE` <= 20140228)
) t1
LEFT SEMI JOIN
(
	SELECT
		产品类型,
		用户ID
	FROM 事实表
	WHERE (`DATE` >= 20140101 AND `DATE` <= 20140131)
) t2 ON (t1.产品类型 = t2.产品类型 AND t1.用户ID = t2.用户ID)
GROUP BY 产品类型


       果然,第2种脚本很快就出来结果了,而第1种脚本还在某个百分点艰难地挪步。。。

       值得注意的是,用了LEFT SEMI JOIN子句以后,右边的表在JOIN操作以外就不可见了,也就是说,右边的表只能在对应的ON子句中被引用。
       以上只是直观的感觉,从定性的层面感受到LEFT SEMI JOIN方式的性能真的是很不错,不晓得这样的效果除了来自Hive本身的官方高效实现外,与公司的生产环境有没有关系。。。
       怎么样,是不是想看看Hive这种特有的方式究竟为我们的查询带来了多大的时间效能改进?是不是也想看看它在源码里究竟是怎样的实现?行动起来吧。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值