Hive支持链接表的如下语法:
sql
本文主要讲hive的joinapache
编写链接查询时要考虑的一些要点以下,不一样版本支持的状况可能会有些许不一样:缓存
1,能够编写复杂的连接表达式,以下安全
SELECT a.* FROM a JOIN b ON (a.id = b.id)
SELECT a.* FROM a JOIN b ON (a.id = b.id AND a.department = b.department)
SELECT a.* FROM a LEFT OUTER JOIN b ON (a.id <> b.id)微信
2,在同一查询中能够链接两个以上的表,例如app
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)运维
3,若是每一个表在链接子句中使用了相同的列,则Hive将多个表上的链接转换为单map/reduce做业
如:机器学习
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)编辑器
上面的sql被转换成一个map / reduce做业,由于只有b的key1列参与了链接。另外一方面oop
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)
上面的sql被转换成两个map / reduce做业,由于来自b的key1列在第一个链接条件中使用,而来自b的key2列在第二个链接条件中使用。第一个map / reduce做业与b链接,而后在第二个map / reduce做业中将结果与c链接。
4,在join的每一个map/reduce stage中,和其它被缓存的表同样,序列中的最后一个表是经过reducer进行流式传输。 所以,经过组织这些表使得最大的表出如今最后一个序列中,能够减小reducer中用于缓冲特定链接键值的行所需的内存。例如
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)
全部这三个表都加入到一个map /reduce 做业中,表a和b的键的特定值的值被缓存在reducer的内存中。 而后,对于从c中检索的每一行,都会使用缓存的行计算链接。
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)
一样的上面的sql有两个map / reduce参与计算链接。其中的第一个join是a和b,并缓存a的值,同时在reducers中流式传输b的值。其中第二个做业缓冲了第一个链接的结果,同时经过reducer流式传输c的值。
5,在每一个链接的map / reduce阶段,能够经过提示来指定要流式传输的表。例如
SELECT /*+ STREAMTABLE(a) */ a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key1)
全部这三个表都加入到一个map / reduce做业中,而且表b和c的键的特定值的值被缓存在reducer中的内存中。而后,对于从a中检索的每一行,都会使用缓冲的行计算链接。若是省略了STREAMTABLE提示,则Hive会将最右边的表加入链接。
6,存在LEFT,RIGHT和FULL OUTER链接,已提供对这些未匹配到的行在on 条件语句上的控制权。例如:
SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key)
这个查询将返回一行中的每一行。当有一个等于a.key的b.key时,这个输出行将是a.val,b.val,当没有相应的b.key时,输出行将是a.val,NULL。从没有对应的a.key的行将被删除。
语法“FROM LEFT OUTER JOIN b”必须写在一行上,以便理解它是如何工做的 - a是在这个查询中在b的左边,因此a中的全部行都保留;
RIGHT OUTER JOIN将保留来自b的全部行,而且FULL OUTER JOIN将保留来自a和b的全部行。OUTER JOIN语义应该符合标准的SQL规范。
7,链接发生在where以前。所以,若是要限制链接的OUTPUT,则须要在WHERE子句中,不然应该在JOIN子句中。这个问题的一大困惑是分区表:
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'
上面的sql将中对a和b进行链接,产生a.val和b.val的列表。可是,WHERE子句也能够引用链接输出中的a和b的其余列,而后将其过滤掉。可是,每当JOIN的某行为b找到一个键而没有键时,b的全部列都将为NULL,包括ds列。这就是说,你将过滤掉没有有效的b.key的全部链接输出行,所以你已经超出了你的LEFT OUTER要求。换句话说,若是在WHERE子句中引用b的任何一列,则链接的LEFT OUTER部分是可有可无的。相反,当外部链接时,使用下面的语法:
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')
结果是链接的输出被预先过滤,而且您将不会获得有一个有效的a.key但没有匹配的b.key行的后过滤的麻烦。相同的逻辑适用于右和全链接。
8,链接不可交换!链接是左关联的,不管它们是左或右链接。
SELECT a.val1, a.val2, b.val, c.val
FROM a
JOIN b ON (a.key = b.key)
LEFT OUTER JOIN c ON (a.key = c.key)
首先对a和b进行join,丢弃在其余表中没有a相应的键的a或b中的全部内容。而后将减少后的表跟c表进行join。这提供了不直观的结果,若是在a和c中都存在一个键,但b中不存在:整个行(包括a.val1,a.val2和a.key)在“a JOIN b”步骤中被删除,由于它不在b中存在。结果没有a.key,因此当它与c进行 LEFT OUTER JOIN的时候,c.val被删除了,由于没有与a.key相匹配的c.key(由于a的那一行被删除了)。一样,若是这是一个RIGHT OUTER JOIN(而不是LEFT),咱们最终会获得一个更奇怪的效果:NULL,NULL,NULL,c.val,由于即便咱们指定了a.key = c.key做为链接键,咱们删除了与第一个JOIN不匹配的全部行。
为了达到更直观的效果,咱们应该改成 FROM c LEFT OUTER JOIN a ON (c.key = a.key) LEFT OUTER JOIN b ON (c.key = b.key).
9,LEFT SEMI JOIN以有效的方式实现不相关的IN / EXISTS子查询语义。从Hive 0.13开始,使用子查询支持IN / NOT IN / EXISTS / NOT EXISTS运算符,所以大多数这些JOIN没必要手动执行。使用LEFT SEMI JOIN的限制是右边的表只能在链接条件(ON子句)中引用,而不能在WHERE或SELECT子句中引用。
SELECT a.key, a.value
FROM a
WHERE a.key in
(SELECT b.key
FROM B);
能够改写为:
SELECT a.key, a.val
FROM a LEFT SEMI JOIN b ON (a.key = b.key)
10,若是除了一个链接的表以外的全部表都很小,则链接能够做为仅map工做来执行。
SELECT /*+ MAPJOIN(b) */ a.key, a.value
FROM a JOIN b ON a.key = b.key
上面的查询不须要reduce。对于每一个mapper,a,b都被彻底读取。限制是不能执行FULL / RIGHT OUTER JOIN b。
11,若是被链接的表在链接列上被分桶,而且一个表中的桶的数量是另外一个表中的桶的数量的倍数,则桶能够彼此链接。若是表A有4个桶,而表B有4个桶,则下列联接
SELECT /*+ MAPJOIN(b) */ a.key, a.value
FROM A a JOIN B b ON a.key = b.key
仅仅在mapper上便可完成链接完成。不是为每一个A的mapper去彻底获取B,而只是获取所需的桶。对于上面的查询,A的映射器处理存储桶1将仅取出B的桶1.它不是默认的行为,可使用如下参数使能:
set hive.optimize.bucketmapjoin = true
12,若是链接的表在链接列上进行排序和分桶,而且具备相同数量的存储桶,则能够执行sort-merge链接。相应的桶在mapper上相互链接。若是A和B都有4个桶,
SELECT /*+ MAPJOIN(b) */ a.key, a.value
FROM A a JOIN B b ON a.key = b.key
上面的功能尽在mapper便可完成。A的桶的映射器将遍历B的相应桶。这不是默认行为,须要设置如下参数:
set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
set hive.optimize.bucketmapjoin = true;
set hive.optimize.bucketmapjoin.sortedmerge = true;
若有疑问请参考官方连接
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Joins
对于hive不一样版本join的不支持状况,浪尖这里给出以下官方截图,:
推荐阅读:
1,hive安装部署
2,Hive : SORT BY vs ORDER BY vs DISTRIBUTE BY vs CLUSTER BY
关于Spark学习技巧
kafka,hbase,spark,Flink等入门到深刻源码,spark机器学习,大数据安全,大数据运维,请关注浪尖公众号,看高质量文章。
更多文章,敬请期待
本文分享自微信公众号 - 浪尖聊大数据(bigdatatip)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。