Hive 中Join的专题---Join详解
1.什么是等值连接?
2.hive转换多表join时,如果每个表在join字句中,使用的都是同一个列,该如何处理?
3.LEFT,RIGHT,FULL OUTER连接的作用是什么?
4.LEFT或RIGHT join是连接从左边还有右边?
Hive表连接的语法支持如下:
Sql代码 :
join_table: table_reference JOIN table_factor [join_condition] | table_reference {LEFT|RIGHT|FULL} [OUTER] JOIN table_reference join_condition | table_reference LEFT SEMI JOIN table_reference join_condition | table_reference CROSS JOIN table_reference [join_condition] (as of Hive 0.10) table_reference: table_factor | join_table table_factor: tbl_name [alias] | table_subquery alias | ( table_references ) join_condition: ON equality_expression ( AND equality_expression )*
hive只支持等连接,外连接,左半连接。hive不支持非相等的join条件(通过其他方式实现,如left outer join),因为它很难在map/reducejob实现这样的条件。而且,hive可以join两个以上的表。
例子
写join查询时,有几个典型的点要考虑,如下:
等连接
只有等连接才允许
Sql代码 :
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)
这两个是合法的连接
Sql代码 :
SELECT a.* FROM a JOIN b ON (a.id <> b.id)
这个是不允许的。
多表连接
同个查询,可以join两个以上的表
Sql代码 :
SELECT a.val, b.val, c.val FROM a JOIN b ON (a.key = b.key1) JOIN c ON (c.key = b.key2)
join的缓存和任务转换
hive转换多表join时,如果每个表在join字句中,使用的都是同一个列,只会转换为一个单独的map/reduce。
Sql代码 :
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被调用。
另一方面
Sql代码 :
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任务,因为b的key1列在第一个join条件使用,而b表的key2列在第二个join条件使用。第一个map/reduce任务join a和b。第二个任务是第一个任务的结果join c。
在join的每个map/reduce阶段,序列中的最后一个表,当其他被缓存时,它会流到reducers。所以,reducers需要缓存join关键字的特定值组成的行,通过组织最大的表出现在序列的最后,有助于减少reducers的内存。
Sql代码 :
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计算。
类似
Sql代码 :
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的值。
在join的每个map/reduce阶段,通过关键字,可以指定哪个表从流接收。
Sql代码 :
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。
join的结果
LEFT,RIGHT,FULL OUTER连接存在是为了提供ON语句在没有匹配时的更多控制。例如,这个查询:
Sql代码 :
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的所有行, FULLOUTER JOIN将会保存a和b的所有行。OUTER JOIN语义应该符合标准的SQL规范。
join的过滤
Joins发生在where字句前,所以,如果要限制join的输出,需要写在where字句,否则写在JOIN字句。现在讨论的一个混乱的大点,就是分区表
Sql代码 :
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'
将会连接a和b,产生a.val和b.val的列表。WHERE字句,也可以引用join的输出列,然后过滤他们。
但是,无论何时JOIN的行找到a的key,但是找不到b的key时,b的所有列会置成NULL,包括ds列。这就是说,将过滤join输出的所有行,包括没有合法的b.key的行。然后你会在LEFT OUTER的要求扑空。
也就是说,如果你在WHERE字句引用b的任何列,LEFTOUTER的部分join结果是不相关的。所以,当外连接时,使用这个语句
Sql代码 :
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'
join的输出会预先过滤,然后你不用对有a.key而没有b.key的行做过滤。RIGHT和FULL join也是一样的逻辑。
join的顺序
join是不可替换的,连接是从左到右,不管是LEFT或RIGHT join。
Sql代码 :
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 jOINb"步骤,被丢弃,因为它不在b中。结果没有a.key,所以当它和c做LEFT OUTER JOIN,c.val也无法做到,因为没有c.key匹配a.key(因为a的行都被移除了)。类似的,RIGHTOUTER JOIN(替换为LEFT),我们最终会更怪的效果,NULL, NULL, NULL, c.val。因为尽管指定了join key是a.key=c.key,我们已经在第一个JOIN丢弃了不匹配的a的所有行。
为了达到更直观的效果,相反,我们应该从
Sql代码 :
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 SEMIJOIN 的限制是, JOIN 子句中右边的表只能在 ON 子句中设置过滤条件,在 WHERE 子句、SELECT 子句或其他地方过滤都不行。
Sql代码 :
SELECT a.key, a.value FROM a WHERE a.key in (SELECT b.key FROM B);
可以重写为
Sql代码 :
SELECT a.key, a.val FROM a LEFT SEMI JOIN b on (a.key = b.key)
mapjoin
但如果所有被连接的表是小表,join可以被转换为只有一个map任务。查询是
SELECT /*+ MAPJOIN(b) */ a.key, a.value FROM a join b ona.key = b.key
不需要reducer。对于每一个mapper,A和B已经被完全读出。限制是a FULL/RIGHTOUTER JOIN b不能使用。
如果表在join的列已经分桶了,其中一张表的桶的数量,是另一个表的桶的数量的整倍,那么两者可以做桶的连接。如果A有4个桶,表B有4个桶,下面的连接:
Sql代码 :
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,这不是默认行为,要使用以下参数:
Sql代码 :
set hive.optimize.bucketmapjoin = true;
如果表在join的列经过排序,分桶,而且他们有相同数量的桶,可以使用排序-合并 join。每个mapper,相关的桶会做连接。如果A和B有4个桶,
Sql代码 :
SELECT /*+ MAPJOIN(b) */ a.key, a.value FROM A a join B b on a.key = b.key
只能在mapper使用。使用A的桶的mapper,也会遍历B相关的桶。这个不是默认行为,需要配置以下参数:
Sql代码 :
set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat; set hive.optimize.bucketmapjoin = true; set hive.optimize.bucketmapjoin.sortedmerge = true;
Hive 中Join的专题---Join详解的更多相关文章
- Hive 中的四种排序详解,再也不会混淆用法了
Hive 中的四种排序 排序操作是一个比较常见的操作,尤其是在数据分析的时候,我们往往需要对数据进行排序,hive 中和排序相关的有四个关键字,今天我们就看一下,它们都是什么作用. 数据准备 下面我们 ...
- 061 hive中的三种join与数据倾斜
一:hive中的三种join 1.map join 应用场景:小表join大表 一:设置mapjoin的方式: )如果有一张表是小表,小表将自动执行map join. 默认是true. <pro ...
- Linux中/proc目录下文件详解
转载于:http://blog.chinaunix.net/uid-10449864-id-2956854.html Linux中/proc目录下文件详解(一)/proc文件系统下的多种文件提供的系统 ...
- JQuery在循环中绑定事件的问题详解
JQuery在循环中绑定事件的问题详解 有个页面上需要N个DOM,每个DOM里面的元素ID都要以数字结尾,比如说 ? 1 2 3 <input type="text" nam ...
- C#中的Linq to Xml详解
这篇文章主要介绍了C#中的Linq to Xml详解,本文给出转换步骤以及大量实例,讲解了生成xml.查询并修改xml.监听xml事件.处理xml流等内容,需要的朋友可以参考下 一.生成Xml 为了能 ...
- 批处理中的echo命令图文详解
批处理中的echo命令图文详解 1. Echo 显示当前ECHO的状态:ECHO ON 或者ECHO OFF 2. ECHO ON 将ECHO状态设置为ON,将显示命令行,也就是前面的C:\>类 ...
- C#中的预处理器指令详解
这篇文章主要介绍了C#中的预处理器指令详解,本文讲解了#define 和 #undef.#if.#elif.#else和#endif.#warning和#error.#region和#endregio ...
- SVN中tag branch trunk用法详解
SVN中tag branch trunk用法详解 2010-05-24 18:32 佚名 字号:T | T 本文向大家简单介绍一下SVN中tag branch trunk用法,SVN中tag bran ...
- JavaScript中的鼠标滚轮事件详解
JavaScript中的鼠标滚轮事件详解/*Firefox注册事件*/ ~~~Firefox: addEventListener('DOMMouseScroll', handler, false)if ...
- php_DWZ-JUI中碰到的问题解决方法详解(thinkphp+dwz)
原文:php_DWZ-JUI中碰到的问题解决方法详解(thinkphp+dwz) 折腾了两天,dwz删除后,数据不能自动刷新,解决方案,直接看图 . 1. 删除.修改状态后无法刷新记录: 在dwz. ...
随机推荐
- 遮挡剔除 Occlusion Culling(转)
一.首先介绍下draw call(这个东西越少你的游戏跑的越快): 在游戏中每一个被展示的独立的部分都被放在了一个特别的包中,我们称之为“描绘指令”(draw call),然后这个包传递到3D部分在屏 ...
- wpgcms---列表页数据渲染
列表页的数据,都是放到 contentList 这样的一个变量里面. {% for x in contentList %} <dl> <dt><a href=" ...
- vue--动态路由和get传值
动态路由: <template> <div id="News"> <v-header></v-header> <hr> ...
- Spark2 加载保存文件,数据文件转换成数据框dataframe
hadoop fs -put /home/wangxiao/data/ml/Affairs.csv /datafile/wangxiao/ hadoop fs -ls -R /datafiledrwx ...
- Linux 将进程放入后台执行,解决网络,ssh断开导致进程结束(nohup, setsid, &, disown)
Linux 将进程放入后台执行,解决网络,ssh断开导致进程结束(nohup, setsid, &, disown) 1.nohup 命令 我们知道,当用户注销(logout)或者网络断开 ...
- mysql bin-logrow模式,base64转正常sql
可以通过以下命令查看日志是否开启查看 show global variables like '%log%'; 当bin-log的模式设置为row时 不仅日志长得快 , 并且查看执行的sql时 , 也稍 ...
- linux使用bin文件安装jdk
jdk1.6.20文件为bin文件安装过程如下 添加执行权限 chmod +x jdk-6u20-linux-x64.bin 运行,出现提示需要输入yes ./jdk-6u20-linux-x64.b ...
- HDFS Snapshots
Overview HDFS Snapshots are read-only point-in-time copies of the file system. Snapshots can be take ...
- 启用mapredure历史服务器方法
在mapred-site.xml配置文件中添加如下信息: <property> <name>mapreduce.jobhistory.addres ...
- JIRA licence and vulnarability,jenkins,devops
http://blog.itpub.net/13651903/viewspace-1079918/ http://www.freebuf.com/articles/web/34051.html JIR ...