Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1108619
  • 博文数量: 143
  • 博客积分: 969
  • 博客等级: 准尉
  • 技术积分: 1765
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-30 12:09
文章分类

全部博文(143)

文章存档

2023年(4)

2021年(2)

2020年(4)

2019年(4)

2018年(33)

2017年(6)

2016年(13)

2014年(7)

2013年(23)

2012年(33)

2011年(14)

我的朋友

分类: 云计算

2018-06-11 20:59:07

1SQL Join

SQL join 用于根据两个或多个表中的列之间的关系,从这些表中查询数据。

SQL join 有四种,以下person表和order表为例来说明

person 表
      

id_p last_name frist_name address city
1 Adams John Oxford Street London
2 Bush George Fifth Avenue New York
3 Carter Thomas Changan Street Beijing


order表

id_o order_num id_p
1 7895 3
2 4467 3
3 2456 1
4 2456 1
5 4764 8

内连接

 内连接也通常称为连接,如果表中有至少一个匹配,则返回行
     SELECT a.last_name, a.frist_name, b.order_num FROM person a JOIN orders  b ON a.id_p=b.id_p;

       

last_name frist_name order_num
Carter Thomas 7895
Carter Thomas 4467
Adams John 2456
Adams John 2456

左连接

  即使右表中没有匹配,也从左表返回所有的行
  SELECT a.last_name, a.frist_name, b.order_num FROM person a LEFT  JOIN orders  b ON a.id_p=b.id_p;

last_name frist_name order_num
Adams John 2456
Adams John 2456
Bush George
Carter Thomas 7895
Carter Thomas 4467

右连接

即使左表中没有匹配,也从右表返回所有的行

SELECT a.last_name, a.frist_name, b.order_num FROM person a RIGHT  JOIN orders  b ON a.id_p=b.id_p;
   

last_name frist_name order_num
Carter Thomas 7895
Carter Thomas 4467
Adams John 2456
Adams John 2456
\N \N 4764

全连接

只要其中一个表中存在匹配,就返回行
SELECT a.last_name, a.frist_name, b.order_num FROM person a  FULL  JOIN orders b ON a.id_p=b.id_p;


last_name frist_name order_num
Carter Thomas 7895
Carter Thomas 4467
Adams John 2456
Adams John 2456
\N \N 4764
Bush George \N

2、MapReduce join

1、  map中进行join(map side join)

主要那个用于以下场景:两个待连接表中,有一个表非常大,而另一个表非常小,以至于小表可以直接存放到内存中。这样,我们可以将小表复制多份,让每个map task内存中存在一份(比如存放到hash table中),然后只扫描大表:对于大表中的每一条记录key/value,在hash table中查找是否有相同的key的记录,如果有,则连接后输出即可。

为了支持文件的复制,Hadoop提供了一个类DistributedCache,使用该类的方法如下:

1)用户使用静态方法DistributedCache.addCacheFile()指定要复制的文件,它的参数是文件的URI(如果是HDFS上的文件,可以这样:hdfs://namenode:9000/home/XXX/file,其中9000是自己配置的NameNode端口号)。JobTracker在作业启动之前会获取这个URI列表,并将相应的文件拷贝到各个TaskTracker的本地磁盘上。

2)用户使用DistributedCache.getLocalCacheFiles()方法获取文件目录,并使用标准的文件读写API读取相应的文件。

2、  reduce中进行 join (reduce side join)

map阶段,map函数同时读取两个文件File1File2,为了区分两种来源的key/value数据对,对每条数据打一个标签(tag,比如:tag=0表示来自文件File1tag=2表示来自文件File2。即:map阶段的主要任务是对不同文件中的数据打标签。

reduce阶段,reduce函数获取key相同的来自File1File2文件的value list, 然后对于同一个key,对File1File2中的数据进行join(笛卡尔乘积)。即:reduce阶段进行实际的连接操作。

3、  半连接(Semi Join)

是从分布式数据库中借鉴过来的方法。它的产生动机是:对于在reducejoin,跨机器的数据传输量非常大,这成了join操作的一个瓶颈,如果能够在map端过滤掉不会参加join操作的数据,则可以大大节省网络IO

实现方法很简单:选取一个小表,假设是File1,将其参与joinkey抽取出来,保存到文件File3中,File3文件一般很小,可以放到内存中。在map阶段,使用DistributedCacheFile3复制到各个TaskTracker上,然后将File2中不在File3中的key对应的记录过滤掉,剩下的reduce阶段的工作与在reduce join相同

4、  reduce中进行 join(reduce side join + BloomFilter)

在某些情况下,半连接抽取出来的小表的key集合在内存中仍然存放不下,这时候可以使用BloomFiler以节省空间。

BloomFilter最常见的作用是:判断某个元素是否在一个集合里面。它最重要的两个方法是:add() contains()。最大的特点是不会存在false negative,即:如果contains()返回false,则该元素一定不在集合中,但会存在一定的true negative,即:如果contains()返回true,则该元素可能在集合中。

因而可将小表中的key保存到BloomFilter中,在map阶段过滤大表,可能有一些不在小表中的记录没有过滤掉(但是在小表中的记录一定不会过滤掉),这没关系,只不过增加了少量的网络IO而已。


阅读(728) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~