整套大数据学习资料(视频+笔记)百度网盘无门槛下载:http://www.edu360.cn/news/content?id=3377

12.7.3 连接

hadoop 小红牛 13℃ 0评论

和直接使用MapReduce相比,使用Hive的一个好处在于Hive简化了常用 操作。对比在MapReduce中实现“连接”(join)要做的事情(参见8.3节), 在Hive中进行连接操作就能充分体现这个好处。

1.内连接

内连接是最简单的一种连接。输入表之间的每次匹配都会在输出表里生成 一行。让我们来考虑两个演示用的小表:sales列出了人名及其所购商品 的ID; things列出商品的ID和名称:

hive> SELECT * FROM sales;
Doe     2
Hank     4
Ali     0
Eve     3
Hank     2
hive> SELECT * FROM things;
2     Tie 
4     Coat
3     Hat
1     Scarf

我们可以像下面这样对两个表进行内连接:

hive> SELECT sales.things.*
> FROM sales 30IN things ON (sales.id = things.id);
Joe   2   2   Tie
Hank  2   2   Tie
Eve   3   3   Hat
Hank  4   4   Coat

FROM子句中的表sales和JOIN子句中的表things用ON子句中的谓词进 行连接。Hive只支持等值连接(equijoin),这意味着在连接谓词中只能使用 等号。在这个示例中,等值条件是两个表的id列必须相同。

有些数据库,例如MySQL和Oracle,允许在SELECT语句的FROM 子句中列出要连接的表,而在WHERE子句中指定连接条件。但是 Hive并不支持这种语法,所以下面的语句会由于解析出错而导致运行 失败:

SELECT sales.*, things.*
FROM sales, things
WHERE sales.id = things.id;

Hive只允许在FROM子句中出现一个表。要进行连接操作,必须遵 循SQL-92中JOIN子句的语法。

在Hive中,可以在连接谓词中使用AND关键字分隔的一系列表达式来连接 多个列。还可以在査询中使用多个JOIN…ON…子句来连接多个表。Hive 会智能地以最少MapReduce作业数来执行连接。

单个的连接用一个MapReduce作业实现。但是,如果多个连接的连接条件 中使用了相同的列,那么平均每个连接可以用少于一个MapReduce作业来 实现。®你可以在査询前使用EXPLAIN关键字来査看Hive将为某个査询使 用多少个MapReduce作业:

EXPLAIN
SELECT sales.things.*
FROM sales JOIN things ON (sales.id = things.id);

EXPLAIN的输出中有很多査询执行计划的详细信息,包括抽象语法树、 Hive执行各阶段之间的依赖图以及每个阶段的信息。一个阶段可能是像

MapReduce作业文件移动这样的一个操作。如果要査看更详细的信息,可以在 查询前使用 EXPLAIN EXTENDED。

Hive目前使用基于规则的査询优化器来确定査询是如何执行的。但在将 来,Hive很有可能会增加一个基于代价的优化器。

 2.外连接

外连接可以让你找到连接表中不能匹配的数据行。在前面的示例里,我们 在进行内连接时,AH那一行没有出现在输出中。因为她所购商品的ID没
有在things表中出现。如果我们把连接的类型改为LEFT OUTER JOIN,
即使左侧表(sales)中的有些行无法与所要连接的表(things)中的任何数据 行对应,査询还是会返回这个表中的每一个数据行:

hive> SELECT sales.*, things.*
> FROM sales LEFT OUTER JOIN things ON (sales.id = things.id)
Ali   0   NULL   NULL
Joe   2   2      Tie
Hank  2   2      Tie
Eve   3   3      Hat
Hank  4   4      Coat

注意,此时返回了 Ali所在的数据行,但因为这一行无匹配,所以things 表的对应列为空值NULL。

Hive也支持“右外连接”(right outer join),即和左连接相比,交换两个表 的角色。在这里,things表中的所有商品,即使没有任何人购买它们 (scarf),也都会被返回:

hive> SELECT sales.*, things.*
> FROM sales RIGHT OUTER 30IN things ON (sales.id = things.id);
NULL   NULL   1  Scarf
Joe     2     2  Tie
Hank    2     2  Tie
Eve     3     3  Hat
Hank    4     4  Coat

最后,还有一种“全外连接”(full outer join),即两个连接表中的所有行在 输出中都有对应的行:

hive> SELECT sales.*, things.*
> FROM sales FULL OUTER JOIN things ON (sales.id = things.id);
Ali   0   NULL   NULL
NULL  NULL 1     Scarf
Joe   2    2     Tie
Hank  2    2     Tie
Eve   3    3     Hat
Hank  4    4     Coat

3.半连接

Hive(在本书这一版写作时)并不支持IN子査询,但可以使用LEFT SEMI JOIN来达到相同的效果。

考虑如下IN子査询,它能够査找things表中在sales表中出现过的所有 商品:

SELECT *
FROM things
WHERE things.id IN (SELECT id from sales);

我们可以像下面这样重写这个査询:

hive〉 SELECT *
>FROM things LEFT SEMI DOIN sales ON (sales.id = things.id);
2   Tie
3   Hat
4   Coat

写LEFT SEMI JOIN査询时必须遵循一个限制:右表(sales)只能在ON子 句中出现。例如,我们不能在SELECT表达式中引用右表。

4.map连接

如果有一个连接表小到足以放入内存,Hive就可以把较小的表放入每个 mapper的内存来执行连接操作。如果要指定使用map连接,需要在SQL中 使用C语言风格的注释,以给出提示:

hive> SELECT /*+ MAP30IN(things) */ sales.*, things.*
>FROM sales DOIN things ON (sales.id = things.id);
Joe  2    2    Tie
Hank 4    4   Coat
Eve  3    3    Hat
Hank 2    2   Tie

执行这个査询不使用reducer,因此这个査询对RIGHT或FULL OUTER JOIN无效,因为只有在对所有输入上进行聚集的步骤(即reduce)才能检测 到哪个数据行无法匹配。

Map连接可以利用分桶的表(参见12.6.2节),因为作用于桶的mapper加载 右侧表中对应的桶即可执行连接。这时使用的语法和前面提到的在内存中 进行连接是一样的,只不过还需要用下面的语法启用优化选项:

SET hive.optimize.bucketmapjoin=true;

转载请注明:全栈大数据 » 12.7.3 连接

喜欢 (0)or分享 (0)
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址