Join与filter的顺序
根据官方文档的说法,join发生在前,filter发生在后。所以如果这样写join sql则会先将整个表join然后在按照where条件过滤:
1 2 |
SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key) WHERE a.ds='2009-07-07' AND b.ds='2009-07-07' |
显然这样背离了初衷。正确的写法应该是:
1 2 |
SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key AND b.ds='2009-07-07' AND a.ds='2009-07-07') |
两种写法虽然感觉是一样的意思,理论上计算出来的结果应该也是一样。但通过实际应用,发现结果居然是不一样的,两者的结果数量可能会相差一个数量级以上,而输出正确的是第二种写法。至于为何第一种写法会出现不一样的结果,等有时间了在研究下。感觉应该是数据的问题,而不是hive有bug。
从日志也可以看到两种语句的map数量不一样,第一种会扫描全表,而第二种只扫描where条件中的特定的partition。
然而以上都不是重点
根据官方文档的说法:
1 2 3 |
..the result is that the output of the join is pre-filtered, and you won't get post-filtering trouble for rows that have a valid a.key but no matching b.key. The same logic applies to RIGHT and FULL joins. |
也就是说join和filter的顺序对RIGHT和FULL join都适用。但是实际上,full join完全不适用。
以下三种写法,全部都是全表扫描!!
1 2 3 4 5 6 7 8 9 10 |
select t.* from demo t full outer join tab_joined s on (t.serv_id=s.prod_id and t.billing_nbr=s.nbr and s.yyyy='2015' and s.mm='07' and s.dd='31'); select t.* from demo t full outer join tab_joined s on (t.serv_id=s.prod_id and t.billing_nbr=s.nbr) where s.yyyy='2015' and s.mm='07' and s.dd='31'; select t.* from demo t full outer join tab_joined s on (t.serv_id=s.prod_id and t.billing_nbr=s.nbr and s.yyyy='2015' and s.mm='07' and s.dd='31') where s.yyyy='2015' and s.mm='07' and s.dd='31'; |
如何才能正常的玩耍?只能这么写:
1 2 3 |
select t.* from demo t full outer join (select * from tab_joined where yyyy='2015' and mm='07' and dd='31') s on (t.serv_id=s.prod_id and t.billing_nbr=s.nbr); |
这样写才能正常的只扫描特定的partition。这一定是个bug!这一定是个bug!这一定是个bug!(自我催眠中)
(转载本站文章请注明作者和出处 程序员的自我修养 – SelfUp.cn ,请勿用于任何商业用途)
分类:Apache Hive
标签:Hive
何总吉祥。。。