一Sqoop是什么
Sqoop是一种用于在Hadoop和关系数据库(RDBMS,如MySQL或Oracle)之间传输数据的工具,使用Sqoop可以批量将数据从关系数据库导入到Hadoop分布式文件系统(HDFS)及其相关系统(如HBase和Hive)中,也可以把Hadoop文件系统及其相关系统中的数据导出到关系数据库中,如下图:
Sqoop基本架构
Sqoop是使用Java语言编写的,Sqoop的架构非常简单,整合了HDFS,HBase和Hive。底层使用MapReduce进行数据传递,从而提供并进行操作和容错功能,如下图:
Sqoop接收到客户端的请求命令后,通过命令翻译器(Task Translater)将命令转换为对应的MapReduce任务,然后通过MapReduce任务将数据在RDBMS和Hadoop系统之间进行导入与导出。
Sqoop导入操作的输入是一个RDBMS数据库表,输出是包含表数据的一系列HDFS文件。导入操作是并行的,可以同时启动多个map任务,每个map任务分别逐行读取表中的一部分数据,并且将这部分数据输出到一个HDFS文件中(即一个map任务对应一个HDFS文件)。
Sqoop导出操作是将数据从HDFS或者Hive导出到关系型数据库中。导出过程并行地读取HDFS上的文件,将每一行内容转化成一条记录添加到关系型数据库表中。除了导入和导出操作,Sqoop还可以查询数据库结构和表信息等。
二Sqoop开发流程
在实际开发中,若数据存储于关系型数据库中,当数据量达到一定规模后需要对其进行分析或统计,此时关系型数据库可能称为瓶颈,这时可以将数据从关系型数据库中导入到HBase中,而后通过数据仓库Hive对HBase中的数据进行统计与分析,并将分析结果存入到Hive表中。最后通过Sqoop将分析结果导出到关系型数据库中作为业务的辅助数据或用于Web页面的展示。
Sqoop的业务开发流程如图所示:
使用Sqoop
要使用Sqoop,需要指定要使用的工具和控制工具的参数。
可以通过进入Sqoop安装目录运行bin/sqoop命令来运行Sqoop。
$ sqoop tool-name [tool-arguments]
Sqoop内置了很多工具,可以通过执行以下命令,显示所有可用工具的列表:
$ sqoop help
常用工具及解析如下:
codegen 生成与数据库记录交互的代码
create-hive-table 导入表的结构到Hive中
eval 执行SQL语句并返回结果
export 导出HDFS目录中的文件数据到数据库表中
help 列出所有可用的工具
import 导入数据库表数据到HDFS中
import-all-tables 导入数据库所有表数到HDFS中
list-databases 列出所有可用数据库
list-tables 列出数据库中所有可用表
version 显示版本信息
也可以执行sqoop help (tool-name)来显示特定工具的帮助信息,例如sqoop help import。还可以将--help参数添加到任何命令,例如sqoop import --help
Sqoop的导入和导出操作主要使用import工具和export工具。这两个工具提供了很多参数帮助我们完成数据的迁移和同步。两个工具中都包含的一些通用参数,如下表所示
|
参数 |
含义 |
|
--connect<jdbc-url> |
指定JDBC连接字符串 |
|
--connection-manager<class-name> |
指定要使用的连接管理器类 |
|
--driver<class-name> |
指定要使用的JDBC驱动类 |
|
--hadoop-mapred-home<dir> |
指定$HADOOP_MAPRED_HOME路径(MapReduce主目录) |
|
--password-file |
设置用于存放认证的密码信息文件的路径 |
|
-P (大写的p) |
从控制台读取设置输入的密码 |
|
--password<password> |
设置认证密码 |
|
--username<username> |
设置认证用户名 |
|
--verbose |
打印详细的运行信息 |
|
--connection-param-file<filename> |
指定存储数据库连接参数的属性文件(可选) |
案例分析一:将mysql表数据导入到HDFS中
创建数据库create databases hdfs_hive; 该数据用于实现mysql表数据导入到hdfs分布式文件系统中。
在MySQL中创建数据库hdfs_hive,并在该表中创建表user_info
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for user_info
-- ----------------------------
DROP TABLE IF EXISTS `user_info`;
CREATE TABLE `user_info` (
`userId` int(20) NOT NULL AUTO_INCREMENT,
`userName` varchar(100) DEFAULT NULL,
`password` varchar(50) DEFAULT NULL,
`trueName` varchar(50) DEFAULT NULL,
`addedTime` date DEFAULT NULL,
PRIMARY KEY (`userId`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user_info
-- ----------------------------
INSERT INTO `user_info` VALUES ('1', '杨洪', '1234565yanghong', 'yanghong', '2020-03-31');
INSERT INTO `user_info` VALUES ('2', '张三', '312321321zhangsan', 'zhangsan', '2020-03-31');
INSERT INTO `user_info` VALUES ('3', '李四', '423432lisi', 'lisi', '2020-03-10');
INSERT INTO `user_info` VALUES ('4', '王五', '234324wangwu', 'wangwu', '2020-03-06');
下面将使用sqoop将表user_info中的数据导入到hdfs中,步骤如下。
1启动Hadoop
在导入数据之前,需要先启动Hadoop集群。执行如下命令,启动Hadoop:
$ start-all.sh
2执行导入命令
执行如下命令,使用Sqoop连接mysql并将表数据到导入到HDFS中
sqoop import \
--connect 'jdbc:mysql://ip:3306/hdfs_hive?characterEncoding=UTF-8' \
--username root \
--password 123456 \
--table user_info \
--columns userId,userName,password,trueName,addedTime \
--target-dir /sqoop/mysql
需要注意的是,”\”后面紧跟回车,表示当前行下一行的续行.
上述代码中各参数含义如下:
--connect: 数据库连接URL
--username: 数据库连接用户名
--password: 数据库密码
--table: 数据库表名
--columns: 数据库列名
--target-dir:数据在HDFS中存放目录。如果HDFS中没有该目录则会自动生成.
20/03/31 21:11:29 INFO mapreduce.Job: map 0% reduce 0%
20/03/31 21:11:38 INFO mapreduce.Job: map 25% reduce 0%
20/03/31 21:11:39 INFO mapreduce.Job: map 50% reduce 0%
20/03/31 21:11:50 INFO mapreduce.Job: map 75% reduce 0%
20/03/31 21:11:53 INFO mapreduce.Job: map 100% reduce 0%
20/03/31 21:11:53 INFO mapreduce.Job: Job job_1585649819788_0001 completed successfully
3查看导入结果
执行下面的命令,查看HDFS中的/sqoop/mysql目录下生成的文件:
$ hadoop fs -ls /sqoop/mysql
-rw-r--r-- 3 hadoop supergroup 0 2020-03-31 21:11 /sqoop/mysql/_SUCCESS
-rw-r--r-- 3 hadoop supergroup 45 2020-03-31 21:11 /sqoop/mysql/part-m-00000
-rw-r--r-- 3 hadoop supergroup 47 2020-03-31 21:11 /sqoop/mysql/part-m-00001
-rw-r--r-- 3 hadoop supergroup 36 2020-03-31 21:11 /sqoop/mysql/part-m-00002
-rw-r--r-- 3 hadoop supergroup 40 2020-03-31 21:11 /sqoop/mysql/part-m-00003
可以看出数据库中的四条数据存储为四个文件,一个文件对应一条数据
执行如下命令,查看/sqoop/mysql/目录下的所有文件的内容:
$ hadoop fs -cat /sqoop/mysql/*
1,杨洪,1234565yanghong,yanghong,2020-03-31
2,张三,312321321zhangsan,zhangsan,2020-03-31
3,李四,423432lisi,lisi,2020-03-10
4,王五,234324wangwu,wangwu,2020-03-06
案例分析二:将HDFS中的数据导出到MySQL中
1在hdfs_hive数据库中创建一个临时表user_info_tmp,字段及类型与表user_info相同,如下:
CREATE TABLE `user_info_tmp` (
`userId` int(20) NOT NULL AUTO_INCREMENT,
`userName` varchar(100) DEFAULT NULL,
`password` varchar(50) DEFAULT NULL,
`trueName` varchar(50) DEFAULT NULL,
`addedTime` date DEFAULT NULL,
PRIMARY KEY (`userId`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
2执行导出命令
执行以下命令,将HDFS文件系统/sqoop/mysql/下的文件中的内容导出到表user_info_tmp中:
sqoop export \
--connect 'jdbc:mysql://ip:3306/hdfs_hive?characterEncoding=UTF-8' \
--username root \
--password 123456 \
--table user_info_tmp \
--export-dir /sqoop/mysql/*
也可以一条一条数据导入
上述代码中各个参数的含义如下:
--table: 目标数据所在的表的名称
--export-dir: 源数据所在的位置
执行成功后输出的部分日志如下:
20/03/31 21:41:44 INFO mapreduce.Job: map 0% reduce 0%
20/03/31 21:41:51 INFO mapreduce.Job: map 100% reduce 0%
20/03/31 21:41:51 INFO mapreduce.Job: Job job_1585649819788_0002 completed successfully