本文主要介绍spark join相关操作。

讲述spark连接相关的三个方法join,left-outer-join,right-outer-join,在这之前,我们用hiveSQL先跑出了结果以方便进行对比。

我们以实例来进行说明。我的实现步骤记录如下。

1、数据准备

2、HSQL描述

3、Spark描述

1、数据准备

我们准备两张Hive表,分别是orders(订单表)和drivers(司机表),通过driver_id字段进行关联。数据如下:

orders

orders表有两个字段,订单id:order_id和司机id:driver_id。司机id将作为连接键。

通过select可以看到三条数据。

hive (gulfstream_test)> select * from orders;
OK
orders.order_id orders.driver_id
1000 5000
1001 5001
1002 5002
Time taken: 0.387 seconds, Fetched: 3 row(s)

drivers

drivers表由两个字段,司机id:driver_id和车辆id:car_id。司机id将作为连接键。

通过select可以看到两条数据。

hive (gulfstream_test)> select * from drivers;
OK
drivers.driver_id drivers.car_id
5000 100
5003 103
Time taken: 0.036 seconds, Fetched: 2 row(s)

2、HSQL描述

JOIN

自然连接,输出连接键匹配的记录。

可以看到,通过driver_id匹配的数据只有一条。

hive (gulfstream_test)> select * from orders t1 join drivers t2 on (t1.driver_id = t2.driver_id) ;
OK
t1.order_id t1.driver_id t2.driver_id t2.car_id
1000 5000 5000 100
Time taken: 36.079 seconds, Fetched: 1 row(s)

LEFT OUTER JOIN

左外链接,输出连接键匹配的记录,左侧的表无论匹配与否都输出。

可以看到,通过driver_id匹配的数据只有一条,不过所有orders表中的记录都被输出了,drivers中未能匹配的字段被置为空。

hive (gulfstream_test)> select * from orders t1 left outer join drivers t2 on (t1.driver_id = t2.driver_id) ;
OK
t1.order_id t1.driver_id t2.driver_id t2.car_id
1000 5000 5000 100
1001 5001 NULL NULL
1002 5002 NULL NULL
Time taken: 36.063 seconds, Fetched: 3 row(s)

RIGHT OUTER JOIN

右外连接,输出连接键匹配的记录,右侧的表无论匹配与否都输出。

可以看到,通过driver_id匹配的数据只有一条,不过所有drivers表中的记录都被输出了,orders中未能匹配的字段被置为空。

hive (gulfstream_test)> select * from orders t1 right outer join drivers t2 on (t1.driver_id = t2.driver_id) ;
OK
t1.order_id t1.driver_id t2.driver_id t2.car_id
1000 5000 5000 100
NULL NULL 5003 103
Time taken: 30.089 seconds, Fetched: 2 row(s)

3、Spark描述

spark实现join的方式也是通过RDD的算子,spark同样提供了三个算子join,leftOuterJoin,rightOuterJoin。

在下面给出的例子中,我们通过spark-hive读取了Hive中orders表和drivers表中的数据,这时候数据的表现形式是DataFrame,如果要使用Join操作:

1)首先需要先将DataFrame转化成了JavaRDD。

2)不过,JavaRDD其实是没有join算子的,下面还需要通过mapToPair算子将JavaRDD转换成JavaPairRDD,这样就可以使用Join了。

下面例子中给出了三种join操作的实现方式,在join之后,通过collect()函数把数据拉到Driver端本地,并通过标准输出打印。

需要指出的是

1)join算子(join,leftOuterJoin,rightOuterJoin)只能通过PairRDD使用;

2)join算子操作的Tuple2<Object1, Object2>类型中,Object1是连接键,我只试过Integer和String,Object2比较灵活,甚至可以是整个Row。

这里我们使用driver_id作为连接键。 所以在输出Tuple2的时候,我们将driver_id放在了前面。

Join.java

/*
* spark-submit --queue=root.zhiliangbu_prod_datamonitor spark-join-1.0-SNAPSHOT-jar-with-dependencies.jar
* */
public class Join implements Serializable { private transient JavaSparkContext javaSparkContext;
private transient HiveContext hiveContext; /*
* 初始化Load
* 创建sparkContext, sqlContext, hiveContext
* */
public Join() {
initSparckContext();
initHiveContext();
} /*
* 创建sparkContext
* */
private void initSparckContext() {
String warehouseLocation = System.getProperty("user.dir");
SparkConf sparkConf = new SparkConf()
.setAppName("spark-join")
.set("spark.sql.warehouse.dir", warehouseLocation)
.setMaster("yarn-client");
javaSparkContext = new JavaSparkContext(sparkConf);
} /*
* 创建hiveContext
* 用于读取Hive中的数据
* */
private void initHiveContext() {
hiveContext = new HiveContext(javaSparkContext);
} public void join() {
/*
* 生成rdd1
* */
String query1 = "select * from gulfstream_test.orders";
DataFrame rows1 = hiveContext.sql(query1).select("order_id", "driver_id");
JavaPairRDD<String, String> rdd1 = rows1.toJavaRDD().mapToPair(new PairFunction<Row, String, String>() {
@Override
public Tuple2<String, String> call(Row row) throws Exception {
String orderId = (String)row.get(0);
String driverId = (String)row.get(1);
return new Tuple2<String, String>(driverId, orderId);
}
});
/*
* 生成rdd2
* */
String query2 = "select * from gulfstream_test.drivers";
DataFrame rows2 = hiveContext.sql(query2).select("driver_id", "car_id");
JavaPairRDD<String, String> rdd2 = rows2.toJavaRDD().mapToPair(new PairFunction<Row, String, String>() {
@Override
public Tuple2<String, String> call(Row row) throws Exception {
String driverId = (String)row.get(0);
String carId = (String)row.get(1);
return new Tuple2<String, String>(driverId, carId);
}
});
/*
* join
* */
System.out.println(" ****************** join *******************");
JavaPairRDD<String, Tuple2<String, String>> joinRdd = rdd1.join(rdd2);
Iterator<Tuple2<String, Tuple2<String, String>>> it1 = joinRdd.collect().iterator();
while (it1.hasNext()) {
Tuple2<String, Tuple2<String, String>> item = it1.next();
System.out.println("driver_id:" + item._1 + ", order_id:" + item._2._1 + ", car_id:" + item._2._2 );
} /*
* leftOuterJoin
* */
System.out.println(" ****************** leftOuterJoin *******************");
JavaPairRDD<String, Tuple2<String, Optional<String>>> leftOuterJoinRdd = rdd1.leftOuterJoin(rdd2);
Iterator<Tuple2<String, Tuple2<String, Optional<String>>>> it2 = leftOuterJoinRdd.collect().iterator();
while (it2.hasNext()) {
Tuple2<String, Tuple2<String, Optional<String>>> item = it2.next();
System.out.println("driver_id:" + item._1 + ", order_id:" + item._2._1 + ", car_id:" + item._2._2 );
} /*
* rightOuterJoin
* */
System.out.println(" ****************** rightOuterJoin *******************");
JavaPairRDD<String, Tuple2<Optional<String>, String>> rightOuterJoinRdd = rdd1.rightOuterJoin(rdd2);
Iterator<Tuple2<String, Tuple2<Optional<String>, String>>> it3 = rightOuterJoinRdd.collect().iterator();
while (it3.hasNext()) {
Tuple2<String, Tuple2<Optional<String>, String>> item = it3.next();
System.out.println("driver_id:" + item._1 + ", order_id:" + item._2._1 + ", car_id:" + item._2._2 );
}
} public static void main(String[] args) {
Join sj = new Join();
sj.join();
} }

执行结果

其中Optional.absent()表示的就是null,可以看到和HSQL是一致的。

Application ID is application_1508228032068_2746260, trackingURL: http://10.93.21.21:4040
****************** join *******************
driver_id:5000, order_id:1000, car_id:100
****************** leftOuterJoin *******************
driver_id:5001, order_id:1001, car_id:Optional.absent()
driver_id:5002, order_id:1002, car_id:Optional.absent()
driver_id:5000, order_id:1000, car_id:Optional.of(100)
****************** rightOuterJoin *******************
driver_id:5003, order_id:Optional.absent(), car_id:103
driver_id:5000, order_id:Optional.of(1000), car_id:100

由于数据量不大,我没有从执行效率上进行考量。

根据经验,一般在数据量较大的情况下,HSQL的执行效率会高一些,如果数据量较小,Spark会快。

 
 

spark三种连接Join的更多相关文章

  1. Sort merge join、Nested loops、Hash join(三种连接类型)

    目前为止,典型的连接类型有3种: Sort merge join(SMJ排序-合并连接):首先生产driving table需要的数据,然后对这些数据按照连接操作关联列进行排序:然后生产probed ...

  2. oracle Hash Join及三种连接方式

    在Oracle中,确定连接操作类型是执行计划生成的重要方面.各种连接操作类型代表着不同的连接操作算法,不同的连接操作类型也适应于不同的数据量和数据分布情况. 无论是Nest Loop Join(嵌套循 ...

  3. SQL 三种基本Join

    Join是关系型数据库系统的重要操作之一,SQL常用Join:内联接.外联接和交叉联接等. 这里讨论一下这常用的三种连接. 测试环境:db2 v10.1, linux 表定义: --用户 CREATE ...

  4. mysql的三种连接方式

    SQL的三种连接方式分为:左外连接.右外连接.内连接,专业术语分别为:LEFT JOIN.RIGHT JOING.INNER JOIN 内连接INNER JOIN:使用比较运算符来根据指定的连接的每个 ...

  5. linux学习之centos(二):虚拟网络三种连接方式和SecureCRT的使用

    ---操作环境--- 虚拟机版本:VMware Workstation_10.0.3 Linux系统版本:CentOS_6.5(64位) 物理机系统版本:win10  一.虚拟网络三种连接方式 当在V ...

  6. [转]Apache HTTP Server 与 Tomcat 的三种连接方式介绍

    首先我们先介绍一下为什么要让 Apache 与 Tomcat 之间进行连接.事实上 Tomcat 本身已经提供了 HTTP 服务,该服务默认的端口是 8080,装好 tomcat 后通过 8080 端 ...

  7. Linux基石【第二篇】虚拟网络三种连接方式(转载)

    在虚拟机上安装完Centos系统后,开始配置静态IP,以方便在本宿主机上可以访问虚拟机,在曲折的配置中,了解到虚拟机还有三种连接方式:Bridged,NAT和Host-only,于是,我又一轮新的各种 ...

  8. Java连接Oracle数据库的三种连接方式

    背景: 这两天在学习Oracle数据库,这里就总结下自己上课所学的知识,同时记录下来,方便整理当天所学下的知识,也同时方便日后自己查询. SQL语句的话,这里我就不多讲了,感觉和其他的数据库(MySQ ...

  9. MySQL的几种连接 join/inner join/cross join/逗号/left join/right join/natural join

    转载请注明出处!! 之前数据表连接操作多使用逗号或者join,对几种连接的概念一直浑浑噩噩,最近研究了一波,把这些连接的区别搞明白了.   连接:A xjoin B(主表 操作 关联表)  selec ...

随机推荐

  1. Maven下载、安装和配置(二)

    前言 在上篇博文[项目管理和构建]--Maven简介(一)中我们了解到maven是一种全新的项目构建方式,让我们的开发更加简单,高效.Maven主要做的是两件事: 统一开发规范与工具 统一管理jar包 ...

  2. 王者荣耀是怎样炼成的(三)unity组件与脚本

    转载请注明出处:http://www.cnblogs.com/yuxiuyan/p/7565345.html 上回书说到了unity的基本操作.这回我们来侃侃unity中的组件与脚本. 目录结构 一. ...

  3. 懒人小工具:T4自动生成Model,Insert,Select,Delete以及导出Excel的方法

    之前写了篇文章,懒人小工具:[自动生成Model,Insert,Select,Delete以及导出Excel的方法](http://www.jianshu.com/p/d5b11589174a),但是 ...

  4. Day-1:初识开发板与基础知识

    买的这款51,ARM,AVR三合一的单片机,也不知道后面具体使用会不会有问题,先玩玩看吧. ------------------------------------------------------ ...

  5. Pro Flight YOKE 设备键位映射踩过的坑

    背景 VR游戏项目.街机游戏项目7月阶段版本快要结束了,考虑到带有键鼠外设显得逼格比较Low,所以决定采用"高大上"的专业设备来进行游戏操作. 需求 需要将键盘鼠标操作的18个键位 ...

  6. PLSQL Developer 连接oracle(64)(instantclient_32)

    下载instantclient-basic-nt-11.2.0.2.0位客户端,加压后存放,如F:\instantclient_11_2 拷贝Oracle 11.2G的msvcr80.dll和tnsn ...

  7. Button标签自动刷新问题

    在form表单中,button标签在IE浏览器 type类型默认是button ,而在其他浏览器默认是submit. 解决方法1: 设置类型type="button" <bu ...

  8. 在前端页面对easyui中的datagrid与jqgrid加载后的数据进行操作

    因为项目的需求,需要在grid中加载数据后再在前端页面执行操作,所以在easyui中的grid与jqgrid都进行了测试和操作: eayui中grid数据的操作: //构造集合对象 var list ...

  9. 数据库中删除语句Drop、Delete、Truncate的相同点和不同点的比较

    数据库删除语句的分别介绍: Delete:用于删除表中的行(注:可以删除某一行:也可以在不删除表的情况下(即意味着表的结构.属性.索引完整)删除所有行) 语法:删除某一行:Delete From 表名 ...

  10. SVN版本控制图标经常延时显示或未显示问题解决方法

    项目中,使用svn经常遇到,文件或文件夹图标延时显示或未显示的问题,终于找到办法解决 客户端:TortoiseSVN