spark三种连接Join
本文主要介绍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的更多相关文章
- Sort merge join、Nested loops、Hash join(三种连接类型)
目前为止,典型的连接类型有3种: Sort merge join(SMJ排序-合并连接):首先生产driving table需要的数据,然后对这些数据按照连接操作关联列进行排序:然后生产probed ...
- oracle Hash Join及三种连接方式
在Oracle中,确定连接操作类型是执行计划生成的重要方面.各种连接操作类型代表着不同的连接操作算法,不同的连接操作类型也适应于不同的数据量和数据分布情况. 无论是Nest Loop Join(嵌套循 ...
- SQL 三种基本Join
Join是关系型数据库系统的重要操作之一,SQL常用Join:内联接.外联接和交叉联接等. 这里讨论一下这常用的三种连接. 测试环境:db2 v10.1, linux 表定义: --用户 CREATE ...
- mysql的三种连接方式
SQL的三种连接方式分为:左外连接.右外连接.内连接,专业术语分别为:LEFT JOIN.RIGHT JOING.INNER JOIN 内连接INNER JOIN:使用比较运算符来根据指定的连接的每个 ...
- linux学习之centos(二):虚拟网络三种连接方式和SecureCRT的使用
---操作环境--- 虚拟机版本:VMware Workstation_10.0.3 Linux系统版本:CentOS_6.5(64位) 物理机系统版本:win10 一.虚拟网络三种连接方式 当在V ...
- [转]Apache HTTP Server 与 Tomcat 的三种连接方式介绍
首先我们先介绍一下为什么要让 Apache 与 Tomcat 之间进行连接.事实上 Tomcat 本身已经提供了 HTTP 服务,该服务默认的端口是 8080,装好 tomcat 后通过 8080 端 ...
- Linux基石【第二篇】虚拟网络三种连接方式(转载)
在虚拟机上安装完Centos系统后,开始配置静态IP,以方便在本宿主机上可以访问虚拟机,在曲折的配置中,了解到虚拟机还有三种连接方式:Bridged,NAT和Host-only,于是,我又一轮新的各种 ...
- Java连接Oracle数据库的三种连接方式
背景: 这两天在学习Oracle数据库,这里就总结下自己上课所学的知识,同时记录下来,方便整理当天所学下的知识,也同时方便日后自己查询. SQL语句的话,这里我就不多讲了,感觉和其他的数据库(MySQ ...
- MySQL的几种连接 join/inner join/cross join/逗号/left join/right join/natural join
转载请注明出处!! 之前数据表连接操作多使用逗号或者join,对几种连接的概念一直浑浑噩噩,最近研究了一波,把这些连接的区别搞明白了. 连接:A xjoin B(主表 操作 关联表) selec ...
随机推荐
- Matlab入门学习(矩阵、函数、绘图的基本使用)
一.矩阵 1.定义和简单使用(一般的编程语言,数组下标都是从0开始的,但是MATLAB是从1开始的) >> a=[ ; ; ] a = >> b=[ ; ; ]; >&g ...
- linux/Windows系统如何安装PHP-openssl扩展
今天倒腾了半天公司的OA办公系统,原来现在很多的smtp服务器是需要ssl方式加密的,而支持ssl需要php加载openssl扩展.所以本文我们将和大家一起分享如何在linux/Windows系统下安 ...
- 基于React Native的移动平台研发实践分享
转载:http://blog.csdn.net/haozhenming/article/details/72772787 本文目录: 一.React Native 已经成为了移动前端技术的趋势 二.基 ...
- java集合系列——List集合之Vector介绍(四)
1. Vector的简介 JDK1.7.0_79版本 Vector 类可以实现可增长的对象数组.与数组一样,它包含可以使用整数索引进行访问的组件.但是,Vector 的大小可以根据需要增大或缩小,以适 ...
- 【模版】AC自动机(简单版)
题目背景 这是一道简单的AC自动机模版题. 用于检测正确性以及算法常数. 为了防止卡OJ,在保证正确的基础上只有两组数据,请不要恶意提交. 题目描述 给定n个模式串和1个文本串,求有多少个模式串在文本 ...
- Sublime Text3使用指南
前言(Prologue) Sublime Text是一款跨平台代码编辑器(Code Editor),从最初的Sublime Text 1.0,到现在的Sublime Text 3.0,Sublime ...
- Jquery实现数据双向绑定(赋值和取值),类似AngularJS
<!DOCTYPE html> <html> <head> <meta name="viewport" content="wid ...
- Sqlite常用sql语句
sqlite常用sql语句 --返回UTC时间 select CURRENT_TIMESTAMP; --返回本地时间 select datetime(CURRENT_TIMESTAMP,'localt ...
- redis的sentinel主从切换(failover)与Jedis线程池自动重连
本文介绍如何通过sentinel监控redis主从集群,并通过jedis自动切换ip和端口. 1.配置redis主从实例 10.93.21.21:6379 10.93.21.21:6389 10.93 ...
- 结束《Java编程思想》(Thinking in Java)自学的读后感(2017.10.15)
首先划重点:这是一本Java的入门书. 自学前需要的条件:已经具备基本的计算机基础. 1)已经对一种编程语言比较熟悉: 2)有过四年计算机专业学习,或者三年以上的软件开发经验, 自学的方法: 1)完全 ...