Hive.WHERE子句的“陷阱”

7 篇文章 0 订阅
5 篇文章 0 订阅

       前天遇到这样一个场景:

       Hive数据仓库里有一个用户访问日志表my_table,这个表对日期字段date (String类型)进行了分区。此外,这个表还有一个字段page_id(Int类型),假定page_id = 9是一个特殊页面。 

       比如我现在要针对日期范围2014-03-17到2014-03-23内去查询每天的UV,并且需要排除对以上提到的特殊页面的统计。那我这样写: 

select 
    `date`, 
    count(distinct user_id) as uv 
from my_table 
where `date` >= 2014-03-17 and `date` <= 2014-03-23 and page_id != 9 or page_id is null 
group by `date`

       在作不等于限定的时候,我们还需要考虑null值,就是需要把null值也纳入计算中。上面这个查询逻辑会出现内存溢出异常:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
       然后回去看脚本,就这么几行,看来看去,以为是查询环境出了问题,然后又试了几次,还是报同样的异常;稍微修改写法,但是自己心里都明白,修改的都应该是无关痛痒的东西。。。果然还是没解决问题,到后来报的异常还稍有变化,出现GC过载神马的了:
Exception in thread "main" java.lang.OutOfMemoryError: GC overhead limit exceeded

       最后,只好邮件寻求数据平台组同事的帮助,结果人家马上就回复:注意后面的括号,也就是说,where子句应该这样写:

where `date` >= 2014-03-17 and `date` <= 2014-03-23 and (page_id != 9 or page_id is null)

       哇嚓,恍然大悟,醍醐灌顶的感觉啊!Hive会把我写的条件解析为

(`date` >= 2014-03-17 and `date` <= 2014-03-23 and page_id != 9) or (page_id is null) 

       也就是说,OR之后的条件独立于OR之前的条件,并没作分区限定!所以它直接要去取每一个分区的数据,做全表扫描啊!内存当然不够咯。

       之前领教过编程语言里运算符结合方向的坑,领教过逻辑运算符的短路计算原则的坑,今天在HQL里领教了WHERE过滤子句的坑。。。不过,都是好坑!

       果然,OR运算的存在,不容忽视。


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值