Apache Sqoop:连接 DB2 和 Hadoop 的桥梁

借助 Sqoop 在 DB2 和 Hadoop 之间进行数据传导

本文将向读者介绍 Apache Sqoop 的基本知识,以及如何利用 Sqoop 在 DB2 与 Hadoop( 包括 Hive 与 HBase) 之间传递数据,帮助读者在大数据和云计算时代更好地管理自己的数据。

刘麒赟, 软件工程师, IBM

刘麒赟刘麒赟,软件工程师,于 2008 年加入 IBM 中国软件开发中心 Data Studio QA and Automation team。目前专职于 IDA、DSD 与 DS 的 QA 工作,以及软件自动化测试工具的应用与开发。



2012 年 12 月 06 日

免费下载:IBM® InfoSphere BigInsights Basic Edition V1.3 试用版
下载更多的 IBM 软件试用版,并加入 IBM 软件下载与技术交流群组,参与在线交流。

概述

随着云计算和物联网等技术在全球的快速发展,企业对大数据 (Big Data) 业务的关注也持续升温。在大数据时代,数据无疑是企业的核心资产之一,若能盘活好数据,则能使企业在公司治理、企业决策和客户服务等方方面面受益匪浅;反之,则在现代企业竞争中,容易导致其核心竞争力下降,甚至衰落。 Apache Hadoop 由于擅长处理大数据分析业务,受到了广大企业的青睐。目前,多数使用 Hadoop 技术处理大数据业务的企业也同时有大量的数据存储于传统的关系型数据库 (RDBMS) 里,如 IBM DB2 数据库。在这种情况下,由于缺乏良好的工具支持,将企业分别存储在 Hadoop 和 DB2 系统里的数据进行传输是一件十分困难的事情,因此也大大限制住了企业更好地对数据进行统一管理和应用。 作为一款协助 RDBMS 与 Hadoop 之间进行数据传导的项目,自从 2009 年 5 月作为 Hadoop 的补丁首次发布以来,Apache Sqoop 逐步迅速发展,并于 2012 年 3 月份正式成为 Apache 的顶级项目。实际上,Sqoop 还能帮助用户在 RDBMS 和 HBase 与 Hive 之间实现数据交流。 本文将以实例演示的方式,向读者介绍 Apache Sqoop 的基本知识,以及如何利用 Sqoop 在 DB2 与 Hadoop( 包括 Hive 与 HBase) 之间传递数据,帮助读者在大数据时代更好地管理和利用自己的数据资产。

Sqoop 简介

Apache Sqoop 项目旨在协助 RDBMS 与 Hadoop 之间进行高效的大数据交流。用户可以在 Sqoop 的帮助下,轻松地把关系型数据库的数据导入到 Hadoop 与其相关的系统 ( 如 HBase 和 Hive) 中;同时也可以把数据从 Hadoop 系统里抽取并导出到关系型数据库里。除了这些主要的功能外,Sqoop 也提供了一些诸如查看数据库表等实用的小工具。

Sqoop 支持的数据库

理论上,Sqoop 支持任何一款支持 JDBC 规范的数据库,如 DB2、MySQL 等。在使用 Sqoop 连接关系型数据库前,首先需要把相关的 JDBC 驱动拷贝到 $SQOOP_HOME/lib 文件夹下,然后在“connect”参数后指定好数据库连接的 url,如“--connect jdbc:db2://localhost:50000/SAMPLE”。 对于 DB2 数据库来说,Sqoop 目前支持 DB2 的绝大多数数据类型,而且 Sqoop 的大多数工具也能在 DB2 上较好地运行。

Sqoop 支持的文件类型

Sqoop 能够将 DB2 数据库的数据导入到 HDFS 上,并保存为多种文件类型。常见的有定界文本类型,Avro 二进制类型以及 SequenceFiles 类型。在本文里,统一用定界文本类型。

环境准备

Sqoop 环境准备

将 Sqoop 项目从 Apache Sqoop 官网 (http://sqoop.apache.org/) 上下载到本地,然后直接解压到本地系统。本文所用的 Sqoop 版本为 1.4.1-incubating。 Sqoop 运行于 Hadoop,因此首先需要确保 Hadoop 环境已经安装好,并且将 Hadoop 的安装路径 (HADOOP_HOME) 添加到系统环境变量中,让 Sqoop 能够找到它。除非 $HADOOP_CONF_DIR 被设置为环境变量,否则 Sqoop 将从 $HADOOP_HOME/conf/ 下寻找 Hadoop 的配置信息。其次,为方便调用 Sqoop 的命令,也最好将 Sqoop 的安装路径 (SQOOP_HOME) 添加到系统环境变量中。另外,如果想要通过 Sqoop 执行与 HBase 和 Hive 相关的操作,也要事先将 HBase 的安装路径 (HBASE_HOME) 和 Hive 的安装路径 (HIVE_HOME) 添加到系统环境变量中。当然,用户也需要提前设置好 JAVA_HOME。

DB2 环境准备

本文将以实例的方式向用户展示如何利用 Sqoop 在 DB2 和 Hadoop 之间、DB2 和 Hive 及 HBase 之间进行数据传导。本实例仅针对其所描述的特定场景来展开描述,用户在应用中应该根据实际情况合理参考利用本实例。本实例中,超市 A 所用到的 DB2 版本为 DB2 LUW 97,而其用表 PRODUCT 来记录它的产品信息,其表结构如图 1 所示。

图 1. PRODUCT 表结构
图 1 PRODUCT 表结构

PRODUCT 表包含的数据如图 2 所示:

图 2. PRODUCT 表数据
图 2 PRODUCT 表数据

最后,需要把连接 DB2 数据库所需要的 JDBC 驱动拷贝到 $SQOOP_HOME/lib 文件夹下。

利用 Sqoop 的 Import 工具将 DB2 数据导出到 Hadoop

目前,超市 A 为了利用 Hadoop 的分布式存储和计算能力来存储和分析它的产品信息,所以首先想要把它存储在 DB2 里的数据信息导入到 HDFS 上面。公司的信息主管 Mike 决定使用 Sqoop 的 Import 工具来帮助他们实现这一目标。 Sqoop 的 Import 工具可以很方便地帮助用户将 DB2 的数据导出到 Hadoop 系统中。用户在调用每一个 Sqoop 工具时,都可以同时使用通用参数 (generic argument) 和特有参数 (specific argument),如“$ sqoop import (generic-args) (import-args)”。 用户可以通过 Sqoop 的 Import 工具提供的特有参数来更好地控制导入过程,其中比较常用的参数如表 1 所示。

表 1. Sqoop Import 主要特有参数
参数作用
connect <jdbc-uri >指定 JDBC 连接字符串
connection-manager <class-name >指定连接管理类
driver <class-name >指定 JDBC 驱动类
hadoop-home <dir >重指定 Hadoop 安装路径
password <password >指定认证密码
username <username >指定认证用户名

当用户不想在命令行中显示地输入密码时,还可以使用通用的参数‘ P ’;同时,用户可以用通用参数‘ m ’来指定本 Job 所用的 map 任务数量,如图 3 所示。由于篇幅限制,本文的许多图中会隐去一些细节,一般仅保留开始的 Sqoop Import 命令,以及最后的 Job 执行情况统计。在图 3 中,可以看到我们在 import 命令中仅指定用一个 map 任务,而在 Job 执行统计中也的确可以看到 Sqoop 完成这个数据导入任务的确只用了一个 map 任务,且并没有使用 reduce 任务。这个 Job 最后从 DB2 数据库中导出了 6 条 ( 行 ) 记录。

图 3. 利用 Sqoop Import 工具导出 DB2 数据库表数据
图 3 利用 Sqoop Import 工具导出 DB2 数据库表数据

执行完 Import 任务后,我们可以在 HDFS 上面看到从 DB2 导出的数据,如图 4 所示。

图 4. 保存在 HDFS 上的 DB2 数据
图 4 保存在 HDFS 上的 DB2 数据

Sqoop 的 Import 工具在本质上是利用 JDBC 来从数据库里面取数据,因此可以通过指定多个 map 任务并行执行来提升其效率——当然,map 任务的数量也并非越多越好,应该根据 Hadoop 集群的实际情况设置。另外一个提升效率的方法是舍弃 Sqoop 默认利用 JDBC 传导数据的方式,而采取别的更有效率的工具——比如数据库提供的数据导出工具。目前,Sqoop 支持用户通过在 Import 命令中添加 --direct 参数来调用 MySQL 自身提供的 mysqldump 工具,以提高数据导出性能。当然,用户也可以自己对 Sqoop 进行扩展,让其支持更多外部的数据导出工具。

利用 Sqoop 的 Export 工具将 Hadoop 的数据导入到 DB2

当将 DB2 中的数据导入到 HDFS 上以后,Mike 决定根据 HDFS 上的数据在 DB2 数据库里的不同 Schema 下创建一张名为“COMMODITY”的表。该表的表结构和 PRODUCT 表完全一样,只是它目前是张空表。此时,他决定借助 Sqoop 的 Export 工具完成这一工作。 与 Import 工具恰好相反,Sqoop 的 Export 工具能够帮助用户将存储在 HDFS 上的数据导入到 DB2。对于用户,这个功能在很多场景下都十分有用。比如,当用户想根据 HDFS 上的数据在数据库里新建一张对应的表;或当用户在 HDFS 上将数据更改后,可以把更改在 DB2 中进行同步;等等。 用户可以通过 Sqoop 的 Export 工具提供的参数来更好地控制导出过程,其中比较常用的参数如表 2 所示。

表 2. Sqoop Export 主要特有参数
参数作用
connect <jdbc-uri >指定 JDBC 连接字符串
connection-manager <class-name >指定连接管理类
driver <class-name >指定 JDBC 驱动类
hadoop-home <dir >重指定 Hadoop 安装路径
password <password >指定认证密码
username <username >指定认证用户名
export-dir <dir >指定导出文件所处的 HDFS 路径
table <table-name >指定要迁入数据的表
update-key <col-name >指定更新表操作所参考的列
update-mode <mode >指定更新表操作的模式
staging-table <staging-table-name >指定暂存数据的分段表
clear-staging-table指定在开始 Export 任务前清空分段表

由于目标表 COMMODITY 已经存在,并且是张空表,所以不用考虑 update-mode 等参数,Mike 直接使用图 5 中的 export 命令成功将数据从 HDFS 导入到 DB2 中的数据表中。

图 5. 利用 Sqoop Export 工具从 HDFS 导入数据到 DB2 数据库表
图 5 利用 Sqoop Export 工具从 HDFS 导入数据到 DB2 数据库表

执行完 Export 任务后,我们可以在 DB2 里面看到从 HDFS 导入的数据,如图 6 所示。

图 6. 导入到 DB2 里的数据
图 6 导入到 DB2 里的数据

除了上面所执行的 Export 命令中所用到的参数,Sqoop Export 任务还有一些其它有用的参数。

update-mode

Sqoop Export 工具默认地会将整个数据迁移工作分解为一系列针对数据库的 Insert 操作。对于数据库中的目标表为空表的情况,这种默认的方法并无不妥之处。但是,如果目标表非空且存在约束,那么 Export 的 Insert 操作就可能会有由于主键冲突等问题而导致的失败。目前,一条 Insert 操作的失败就会导致整个 Sqoop Export 任务的失败。 为了规避以上描述的问题产生,用户可以利用 update-mode 参数。update-mode 参数定义了更新表操作的模式。它有两种模式:

  • updateonly
  • allowinsert

第一种模式 (updateonly) 是默认的模式,它会把整个 Export 的数据迁移工作分解为一系列的 Update 操作。而当更新表操作所参考的列则可以通过参数 update-key <col-name > 来指定。这种模式下,对于那些并不影响到已存在的表数据的 Update 操作 ( 比如,要 Update 的行在数据表中本来并不存在 ),不会导致任何失败,但也不会更新任何数据。但如果用户想在更新已存在的行的同时插入那些原先并不存在的行,就可以使用 allowinsert 模式——在这种模式下,对于不存在的列的操作会是 Insert,而非 Update。用户可以根据实际情况,合理选择 update-mode。

staging-table

正如上文所介绍的情况,当执行 Export 命令时,一条 Insert 语句的失败可能会导致整个 Export 任务的失败,但此时可能已经有部分数据插入到了数据库表中——这将会引起数据不完整的问题。一个理想的状态应该是要么所有数据都成功地更新进数据库,要么数据库没有带来任何更新。为了解决这个问题,用户可以事先在数据库中创建一张临时表作为存储中间数据的分段表 (staging table)。分段表的结构和目标表完全一样,只有当所有命令都成功执行完后,数据才会从分段表转移到目标表里;而当任务失败时,目标表不会受到任何影响。 在使用 staging-stable 参数时,用户可以同时使用 clear-staging-table 参数——该参数确保在开始 Export 任务前清空分段表。

利用 Sqoop 将 DB2 的数据导入到 Hive

在决定使用 Hadoop 作为公司信息处理的平台后,公司的信息主管 Mike 现在想把超市 A 中有关产品的信息都放到一个基于 Hadoop 的数据仓库中,以更好地分析企业的数据。这时,他选择了 Hive ——一个基于 Hadoop 的数据仓库工具,它支持 SQL 查询 ( 最终会把 SQL 语句转化为 MapReduce 任务以执行 )。 Sqoop 提供将数据库的数据直接导入到 Hive 的功能,并提供了一些相关的参数 ( 如表 3 所示 )。

表 3. Sqoop 导入数据到 Hive 相关的主要参数
参数作用
hive-import导入数据到 Hive
hive-overwrite覆盖 Hive 中已存在的数据
create-hive-table指定在 Hive 中创建新的数据表类
hive-home <dir >重指定 Hive 安装路径
hive-table <table-name >指定导入数据的 Hive 表名

用户可以使用 create-hive-table 命令,在 Hive 中创建对应于 DB2 数据库的 PRODUCT 表。

图 7. 创建 Hive 表
图 7 创建 Hive 表

而信息主管 Mike 则成功利用 hive-import 直接在 Hive 中创建对应于 DB2 表,并导入其数据。

图 8. 导入 DB2 数据表到 Hive
图 8 导入 DB2 数据表到 Hive

利用 Sqoop 将 DB2 的数据导入到 HBase

现在,公司的信息主管 Mike 想接受进一步的挑战:在 Hadoop 上运行能够提供在线实时服务的数据库。经过权衡,他最终选择了 HBase。HBase 建立在 Hadoop 之上,是一个分布式的、面向列的开源数据库。而且,与 Hive 一样,HBase 最终也是利用 Hadoop 的 MapReduce 来处理数据。 在安装完 HBase 数据库后,Mike 想把 DB2 里的数据也导入到 HBase 中。幸运的是,Sqoop 支持将数据库数据传输到 HBase,并为此提供了一些相关的参数 ( 如表 4 所示 )。

表 4. Sqoop 导入数据到 HBase 相关的主要参数
参数作用
column-family <family >指定 HBase 的列族
hbase-create-table指定在 HBase 中创建缺失的数据表
hbase-row-key <col >指定 HBase 的 row key
hbase-table <table-name >指定导入数据的 HBase 表名

Mike 最终利用 Sqoop,在 HBase 中导入了 DB2 数据库的 PRODUCT 表。

图 9. 导入 DB2 数据表到 HBase
图 9 导入 DB2 数据表到 HBase

结束语

Sqoop 作为传统数据库与 Hadoop 之间的桥梁,可以在数据迁移方面为用户提供有力的支持。

参考资料

学习

获得产品和技术

讨论

  • 访问 developerWorks 博客,加入 developerWorks 中文社区,developerWorks 社区是一个面向全球 IT 专业人员,可以提供博客、书签、wiki、群组、联系、共享和协作等社区功能的专业社交网络社区。

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Information Management
ArticleID=850367
ArticleTitle=Apache Sqoop:连接 DB2 和 Hadoop 的桥梁
publish-date=12062012