本节书摘来异步社区《Hadoop实战手册》一书中的第1章,第1.4节,作者: 【美】Jonathan R. Owens , Jon Lentz , Brian Femiano 译者: 傅杰 , 赵磊 , 卢学裕 责编: 杨海玲,更多章节内容可以访问云栖社区“异步社区”公众号查看。
1.4 使用Sqoop从MySQL数据库导入数据到HDFS
Sqoop是Apache基金下的一个项目,是庞大Hadoop生态圈中的一部分。在很多方面Sqoop和distcp很相似(见1.3节)。这两个工具都是构建在MapReduce之上的,利用了MapReduce的并行性和容错性。与集群间的数据复制不同,Sqoop设计通过JDBC驱动连接实现Hadoop集群与关系数据库之间的数据复制。
它的功能非常广泛,本节将以网络日志条目为例展示如何使用Sqoop从MySQL数据库导入数据到HDFS。
准备工作
本例子使用Sqoop V1.3.0版本。
如果你使用的是CDH3版本,Sqoop默认是已经安装了。如果不是CDH3,你可以通过https://ccp.cloudera.com/display/CDHDOC/Sqoop+Installation找到发行版的说明。
在本节假设你已经启动了一个MySQL实例,并且能够访问Hadoop集群6。mysql.user该表配置了你运行Sqoop的那台机器上被允许连接的用户。访问http://dev.mysql.com/doc/refman/5.5/en/installing.html获取更多关于MySQL安装与配置的相关信息。
将MySQL JDBC驱动包复制到$SQOOP_HOME/libs7目录下。该驱动包可以从http://dev.mysql.com/downloads/connector/j/下载。
操作步骤
完成以下步骤实现将MySQL表数据导出到HDFS中。
1.在MySQL实例中创建一个新数据库:
CREATE DATABASE logs;
2.创建并载入表weblogs:
USE logs;
CREATE TABLE weblogs (
md5 VARCHAR(32),
url VARCHAR(64),
request_date DATE,
request_time TIME,
ip VARCHAR(15)
);
LOAD DATA INFILE '/path/weblog_entries.txt' INTO TABLE weblogs
FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\r\n';
3.查询weblogs表的行数:
mysql> select count(*) from weblogs;
输出结果将会是:
+----------+
| count(*) |
+----------+
| 3000 |
+----------+
1 row in set (0.01 sec)
4.将MySQL数据导出到HDFS:
sqoop import -m 1 --connect jdbc:mysql://<HOST>:<PORT>/logs--username hdp_usr --password test1 --table weblogs --target-dir /data/weblogs/import
输出结果将会是:
INFO orm.CompilationManager: Writing jar file:
/tmp/sqoop-jon/compile/f57ad8b208643698f3d01954eedb2e4d/weblogs. jar
WARN manager.MySQLManager: It looks like you are importing from mysql.
WARN manager.MySQLManager: This transfer can be faster! Use the --direct
WARN manager.MySQLManager: option to exercise a MySQL-specific fast path.
...
INFO mapred.JobClient: Map input records=3000
INFO mapred.JobClient: Spilled Records=0
INFO mapred.JobClient: Total committed heap usage (bytes)=85000192
INFO mapred.JobClient: Map output records=3000
INFO mapred.JobClient: SPLIT_RAW_BYTES=87
INFO mapreduce.ImportJobBase: Transferred 245.2451 KB in 13.7619 seconds
(17.8206 KB/sec)
INFO mapreduce.ImportJobBase: Retrieved 3000 records.
工作原理
Sqoop连接数据库的JDBC驱动在--connect语句中定义,并从$SQOOP_HOME/libs目录中加载相应的包,其中$SQOOP_HOME为Sqoop安装的绝对路径。--username和--password选项用于验证用户访问MySQL实例的权限。mysql.user表必须包含Hadoop集群每个节点的主机域名以及相应的用户名,否则Sqoop将会抛出异常,表明相应的主机不允许被连接到MySQL服务器。
mysql> USE mysql;
mysql> select host, user from user;
显示输出如下:
+-------------+-----------+
| user | host |
+-------------+-----------+
| hdp_usr | hdp01 |
| hdp_usr | hdp02 |
| hdp_usr | hdp03 |
| hdp_usr | hdp04 |
| root | 127.0.0.1 |
| root | ::1 |
| root | localhost |
+-------------+-----------+
7 rows in set (1.04 sec)
在这个例子中,我们使用hdp_usr用户连接到MySQL服务器。我们的集群拥有4台机器,即hdp01、hdp02、hdp03和hdp04。
--table变量告诉Sqoop哪个表需要被导入。在我们的例子中,是要导入weblogs这个表到HDFS。--target-dir变量决定了导出的表数据将被存储在HDFS的哪个目录下:
hadoop fs -ls /data/weblogs/import
输出结果为:
-rw-r--r-- 1 hdp_usr hdp_grp 0 2012-06-08 23:47 /data/
weblogs/import/_SUCCESS
drwxr-xr-x- - hdp_usr hdp_grp 0 2012-06-08 23:47 /data/
weblogs/import/_logs
-rw-r--r-- 1 hdp_usr hdp_grp 251131 2012-06-08 23:47 /data/
weblogs/import/part-m-00000
默认情况下,导入的数据将按主键进行分割。如果导入的表并不包含主键,必须指定-m或者--split-by参数决定导入的数据如何分割。在前面的例子中,使用了-m参数。-m参数决定了将会启动多少个mapper来执行数据导入。因为将-m设置为1,所以就启动了一个mapper用于导入数据。每个mapper将产生一个独立的文件。
这行命令背后隐藏了相当复杂的逻辑。Sqoop利用数据库中存储的元数据生成每一列的DBWritable类,这些类使用了DBInputFormat。DBInputFormat是Hadoop用来格式化读取数据库任意查询的结果。在前面的例子中,启动了一个使用DBInputFormat索引weblogs表内容的MapReduce作业。整个weblogs表被扫描并存储在HDFS的路径/data/weblogs/import下。
更多参考
使用Sqoop导入数据还有很多有用的参数可以配置。Sqoop可以分别通过参数--as-avrodatafile和--as-sequencefile将数据导入为Avro文件和序列化的文件。通过-z或者--compress参数可以在导入的过程中对数据进行压缩。默认的压缩方式为GZIP压缩,可以通过--compression-codec 参数使用Hadoop支持的任何压缩编码。可以查看第2章的使用LZO压缩数据那一节的介绍。另一个有用的参数是--direct,该参数指示Sqoop直接使用数据库支持的本地导入导出工具。在前面的例子中,如果--direct被添加为参数,Sqoop将使用mysqldump工具更快地导出weblogs表的数据。--direct参数非常重要以至于我们在运行前面的日志会打印出如下的日志信息:
WARN manager.MySQLManager: It looks like you are importing from mysql.
WARN manager.MySQLManager: This transfer can be faster! Use the --direct
WARN manager.MySQLManager: option to exercise a MySQL-specific fast path.
延伸阅读
- 使用Sqoop从HDFS导出数据到MySQL(1.5节)。