hive只支持等链接,外链接,左半链接。hive不支持非相等的join条件(经过其余方式实现,如left outer join),由于它很难在map/reduce中实现这样的条件。并且,hive能够join两个以上的表。html
只有等链接才容许jquery
hive> SELECT a.* FROM a JOIN b ON (a.id = b.id); hive> SELECT a.* FROM a JOIN b ON (a.id = b.id AND a.department = b.department);
同个查询,能够join两个以上的表apache
hive> SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2);
hive转换多表join时,若是每一个表在join字句中,使用的都是同一个列,只会转换为一个单独的map/reduce。缓存
hive> 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任务,由于b的key1列在第一个join条件使用,而b表的key2列在第二个join条件使用。第一个map/reduce任务join a和b。第二个任务是第一个任务的结果join c。app
hive> SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2);
在join的每一个map/reduce阶段,序列中的最后一个表,当其余被缓存时,它会流到reducers。因此,reducers须要缓存join关键字的特定值组成的行,经过组织最大的表出如今序列的最后,有助于减小reducers的内存。oop
hive> 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任务作join。a和b的key对应的特定值组成的行,会缓存在reducers的内存。而后reducers接受c的每一行,和缓存的每一行作join计算。学习
hive> SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2);
这里有两个map/reduce任务在join计算被调用。第一个是a和b作join,而后reducers缓存a的值,另外一边,从流接收b的值。第二个阶段,reducers缓存第一个join的结果,另外一边从流接收c的值。spa
在join的每一个map/reduce阶段,经过关键字,能够指定哪一个表从流接收。code
hive> 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任务,reducer会把b和c的key的特定值缓存在内存里,而后从流接收a的每一行,和缓存的行作join。orm
LEFT,RIGHT,FULL OUTER链接存在是为了提供ON语句在没有匹配时的更多控制。例如,这个查询:
hive> SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key);
将会返回a的每一行。若是b.key等于a.key,输出将是a.val,b.val,若是a没有和b.key匹配,输出的行将是 a.val,NULL。若是b的行没有和a.key匹配上,将被抛弃。语法"FROM a LEFT OUTER JOIN b"必须写在一行,为了理解它如何工做——这个查询,a是b的左边,a的全部行会被保持;RIGHT OUTER JOIN将保持b的全部行, FULL OUTER JOIN将会保存a和b的全部行。OUTER JOIN语义应该符合标准的SQL规范。
Joins发生在where字句前,因此,若是要限制join的输出,须要写在where字句,不然写在JOIN字句。如今讨论的一个混乱的大点,就是分区表
hive> SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key) WHERE a.ds='2018-05-22' AND b.ds='2018-05-22';
将会链接a和b,产生a.val和b.val的列表。WHERE字句,也能够引用join的输出列,而后过滤他们。 可是,不管什么时候JOIN的行找到a的key,可是找不到b的key时,b的全部列会置成NULL,包括ds列。这就是说,将过滤join输出的全部行,包括没有合法的b.key的行。而后你会在LEFT OUTER的要求扑空。 也就是说,若是你在WHERE字句引用b的任何列,LEFT OUTER的部分join结果是不相关的。因此,当外链接时,使用这个语句
hive> SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON (a.key=b.key AND b.ds='2018-05-22' AND a.ds='2018-05-22';
join的输出会预先过滤,而后你不用对有a.key而没有b.key的行作过滤。RIGHT和FULL join也是同样的逻辑。
join是不可替换的,链接是从左到右,不论是LEFT或RIGHT join。
hive> 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,扔掉a和b中没有匹配的key的行。结果表再链接c。这提供了直观的结果,若是有一个键都存在于A和C,但不是B:完整行(包括 a.val1,a.val2,a.key)会在"a jOIN b"步骤,被丢弃,由于它不在b中。结果没有a.key,因此当它和c作LEFT OUTER JOIN,c.val也没法作到,由于没有c.key匹配a.key(由于a的行都被移除了)。相似的,RIGHT OUTER JOIN(替换为LEFT),咱们最终会更怪的效果,NULL, NULL, NULL, c.val。由于尽管指定了join key是a.key=c.key,咱们已经在第一个JOIN丢弃了不匹配的a的全部行。
为了达到更直观的效果,相反,咱们应该从
hive> FROM c LEFT OUTER JOIN a ON (c.key = a.key) LEFT OUTER JOIN b ON (c.key = b.key);
LEFT SEMI JOIN实现了相关的IN / EXISTS的子查询语义的有效途径。因为Hive目前不支持IN / EXISTS的子查询,因此你能够用 LEFT SEMI JOIN 重写你的子查询语句。LEFT SEMI JOIN 的限制是, JOIN 子句中右边的表只能在 ON 子句中设置过滤条件,在 WHERE 子句、SELECT 子句或其余地方过滤都不行。
hive> SELECT a.key, a.value FROM a WHERE a.key in (SELECT b.key FROM B);
能够重写为
hive> SELECT a.key, a.val FROM a LEFT SEMI JOIN b on (a.key = b.key);
但若是全部被链接的表是小表,join能够被转换为只有一个map任务。查询是
hive> SELECT /*+ MAPJOIN(b) */ a.key, a.value FROM a join b on a.key = b.key;
不须要reducer。对于每个mapper,A和B已经被彻底读出。限制是a FULL/RIGHT OUTER JOIN b不能使用。
若是表在join的列已经分桶了,其中一张表的桶的数量,是另外一个表的桶的数量的整倍,那么二者能够作桶的链接。若是A有4个桶,表B有4个桶,下面的链接:
hive> SELECT /*+ MAPJOIN(b) */ a.key, a.value FROM a join b on a.key = b.key;
只能在mapper工做。为了为A的每一个mapper完整抽取B。对于上面的查询,mapper处理A的桶1,只会抽取B的桶1,这不是默认行为,要使用如下参数:
hive> set hive.optimize.bucketmapjoin = true;
若是表在join的列通过排序,分桶,并且他们有相同数量的桶,可使用排序-合并 join。每一个mapper,相关的桶会作链接。若是A和B有4个桶
hive> SELECT /*+ MAPJOIN(b) */ a.key, a.value FROM A a join B b on a.key = b.key;
只能在mapper使用。使用A的桶的mapper,也会遍历B相关的桶。这个不是默认行为,须要配置如下参数:
hive> set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat; hive> set hive.optimize.bucketmapjoin = true; hive> set hive.optimize.bucketmapjoin.sortedmerge = true;
以上就是博主为你们介绍的这一板块的主要内容,这都是博主本身的学习过程,但愿能给你们带来必定的指导做用,有用的还望你们点个支持,若是对你没用也望包涵,有错误烦请指出。若有期待可关注博主以第一时间获取更新哦,谢谢!