Spark中External Datasource实现数据迁移

来源:互联网 发布:王珊数据库视频教程 编辑:程序博客网 时间:2024/06/08 08:25

一、简介

1.技术说明

通过一套DataSource API的扩展机制,可以访问(读、写)外部的数据源。将外部数据源按照表的方式注册,提供sql查询、数据插入(insert)能力。将外部数据源读取为RDD,提供RDD的算子(groupwhereagg)、ML能力。当前可以对接的外部数据源:JDBCElasticSearch等。

2.优点

将外部数据源纳入到spark的生态系统,如oracle不支持预测分析,通过spark读取oracle数据转换为rdd,就可以利用sparkML的算法。

统一数据源的访问方式,如注册为表,则都可以通过sparksql方言访问各类数据源。

在数据源的读写能力之上,既可以提供跨数据源的数据迁移。如从kafka中获取数据写入到hdfs,然后通过注册ES外部数据源,将数据装载到ES中,最后通过sparksql访问ES

二、需求场景

从各类数据源中抽取数据集,存储到SparkSQL的查询引擎中,对外提供自助分析。数据源支持如hiveoralcevertica等,其实hive和加速引擎有可能不是一个Hadoop集群。从外部数据源获取数据集支持以SQL查询的方式提取数据集。

三、实现说明

1、API介绍

SQLContext

DataFrameReader

read() 

 

DataFrameReader

Dataset<Row>

jdbc(String url, String table, java.util.Properties properties)

Construct a DataFrame representing the database table accessible via JDBC URL url named table and connection properties.

Dataset<Row>

jdbc(String url, String table, String[] predicates, java.util.Properties connectionProperties)

Construct a DataFrame representing the database table accessible via JDBC URL url named table using connection properties.

Dataset<Row>

jdbc(String url, String table, String columnName, long lowerBound, long upperBound, int numPartitions, java.util.Properties connectionProperties)

Construct a DataFrame representing the database table accessible via JDBC URL url named table.

 

Dataset

DataFrameWriter<T>

write()

Interface for saving the content of the non-streaming Dataset out into external storage

 

DataFrameWriter<T>

void

jdbc(String url, String table, java.util.Properties connectionProperties)

Saves the content of the DataFrame to an external database table via JDBC

DataFrameWriter<T>

mode(SaveMode saveMode)

Specifies the behavior when data or table already exists.

Void

save(Stringpath)

Saves the content of the DataFrame at the specified path.

 

 

参考:http://spark.apache.org/docs/latest/api/java/index.html

 

2、API使用说明

实现功能:将JDBC数据源中多张表的查询结果,写入到HDFS Path

方案一:

sqlContext.read().jdbc(url,“([SQL Query]) t,properties).write().savepath

说明:

1、SQL QueryJDBC数据源的查询。在sparksql使用该JDBC数据源的驱动访问数据库的时候将([SQL Query]) t拼装成select * from ([SQL Query]) t的查询,从而实现在JDBC数据源上直接执行查询。

2、save函数之前可以通过mode函数制定写入的方式。

3、SQL Query是外部数据源的sql方言。那是否可以通过sparksql的方言来执行该查询?从技术行将是可以的,即将外部数据源的表都注册为external table,见方案二。

方案二:

1、注册为external table的方式

a) 使用APISQLContext中提供多个“createExternalTable”的API

b) Spark提供的sql语法来创建外部表

2、举例已经注册了两个外部表ft1ft2,分别对应外部数据源上的pt1pt2。使用如下一行代码可实现类似的效果

sqlContext.read().sql([SQL Query]),properties).write().savepath

3、此时的SQL Query即为sparksql方言

和方案一对比:

1、优点:实现了方言统一

2、缺点:spark内部在执行SQL Query的是没有做谓词下推的,实现方式是将pt1pt2的表抽取到sparkrdd中然后用spark引擎做运算。在联邦场景或外部数据源是哑存储的情况下,该方式可以接受。但是对于JDBC数据源,显然没有方案一性能高。

方案三:在方案二基础上实现谓词下推

按照方案二的例子,即”注册了两个外部表ft1ft2,分别对应外部数据源上的pt1pt2。在注册为ft1表的时候,对pt1做过滤。涉及到Dataset如下API

Dataset

ataset<T>

filter(Column condition)

Filters rows using the given condition.

Dataset<Row>

drop(Column col)

Returns a new Dataset with a column dropped.

 

 

使用如下的语句可实现谓词下推。SQL Query中使用到ft1的时候,会按照dropfilter的设置提取相应的数据。

Dataset ds=SQLContext.createExternalTable(“ft1”...).drop().filter

缺点:对于where中有布尔运算的情况下,不容易实现filter的谓词下推。如SQL Querywhere部分的条件为(ft1.c1>1 or ft2.c2 >10)需要解析该谓词判断如何注册定义ft1ft2表。

方案四:

sparksqlsql方言转换成外部数据源的执行计划,在某些情况下可实现方案一的效果。不过需要如下多种情况:

1、仅单数据源查询

2、对应数据源无法处理某些sql函数的情况下

3、联邦的情况。

方案四复杂度最高。

优选方案一,方案三是通用方案,需要增加谓词下压的解析模块。

 

3、部署执行

如上,通过scalajava方式开发job需要将该job提交到spark集群中运行。使用sparkthriftserver笔者猜测实现的功能是受限的。注册两个外表ft1ft2,在jdbc驱动链接到thriftserver执行insert ft1 select ft2实现数据迁移,但是功能远远没有API丰富,如无法指定保存的模式等等。

 

 

四、DataSource API技术原理

1.技术原理

直接看这个博文即可(http://blog.csdn.net/oopsoom/article/details/42064075)。虽然最新的spark版本是2.1了,仍有参考意义。

2.扩展方式

在上节给出的博文已经给出扩展方式。另外还需要考虑数据类型的转换器的注册。在sparksql的表saveoracle的时候,通过直接推断每个字段的类型,直接在oracle上创建了表,利用的就是数据类型转换器的功能。

 

 

 

原创粉丝点击