返回 导航

大数据

hangge.com

Sqoop - 数据库离线数据采集工具使用详解2(样例1:Mysql数据导入HDFS)

作者:hangge | 2024-04-09 09:11

二、实现将 Mysql 数据导入HDFS

1,准备工作

(1)为了演示如何将 MySQL 中指定表的数据导入 HDFS 中,首先我们在 MySQL 中创建一张 user 表:
CREATE TABLE `user` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) DEFAULT NULL,
  `phone` varchar(64) DEFAULT NULL,
  PRIMARY KEY (`id`)
);

(2)接着在该表中插入 4 条数据:
INSERT INTO user (id, name, phone) VALUES ('1', 'lilei', null);
INSERT INTO user (id, name, phone) VALUES ('2', 'xiaoliu', '888888');
INSERT INTO user (id, name, phone) VALUES ('3', 'hangge', '123456');
INSERT INTO user (id, name, phone) VALUES ('4', 'baidu', null);

2,全表导入样例

(1)下面命令使用 Sqoop 将表 user 中的数据导入 HDFS 中:
(1)如果表 user 中没有主键,并且 Sqoop 命令中也没有设置 --num-mappers 1,则下面的 Sqoop 命令执行会报错,因为 MapReduce 任务中的 Map 任务数默认是 4,需要分 4Map 任务,每个 Map 任务计算一部分数据,但是表 user 没有主键,所以 MapReduce 不知道以哪个字段为基准来拆分数据。
(2)解决办法可以选择下面其中一种:
  • 在表中设置主键,默认根据主键字段拆分数据。
  • 使用 --num-mappers 1,表示将 Map 任务个数设置为 1,这样就不需要拆分数据了。
  • 使用 --split-by,后面指定一个数字类型的列,MapReduce 会根据这个列拆分数据。
sqoop import \
--connect jdbc:mysql://192.168.60.1:3306/hangge?serverTimezone=UTC \
--username root \
--password hangge1234 \
--table user \
--target-dir /out1 \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by '\t'

(2)控制台输出如下内容说明任务执行完毕:

(3)看到 HDFS 上也创建了对应的目录和文件:

(4)打开文件可以看到里面便是从数据库中导出的数据:

3,查询导出样例

(1)下面命令使用 SQL 语句查询表中满足条件的数据(id>1)并将其导入 HDFS 中。
注意:
  • 在使用 --query 指定 SQL 语句时,其中必须包含 $CONDITIONS
  • --query --table 这两个参数不能在一个 Sqoop 命令中同时指定。
sqoop import \
--connect jdbc:mysql://192.168.60.1:3306/hangge?serverTimezone=UTC \
--username root \
--password hangge1234 \
--target-dir /out2 \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by '\t' \
--query 'select id,name,phone from user where id >1 and $CONDITIONS;' 

(2)查看 HDFS 上的文件,里面内容只有复合查询条件的数据:

4,NULL 值处理样例

(1)在默认情况下,MySQL 中的 NULL 值(无论字段类型是字符串类型还是数字类型)在使用 Sqoop 导入 HDFS 后会显示为字符串 null

(2)我们可以通过参数来设置NULL值的替换方式:
  • 对于字符串的 NULL 类型:通过 --null-string '*' 来指定。在单引号中指定字符串,这个字符串不能是 --,因为 -- 是保留关键字。
  • 对于非字符串的 NULL 类型:通过 --null-non-string '=' 来指定。在单引号中指定字符串,这个字符串不能是 --,因为 -- 是保留关键字。
注意:
  • 这两个参数可以同时设置,这样在做数据导入时,空值字段会被替换为指定的字符串内容。
  • --null-string --null-non-string 后面指定字符串时不能使用双引号,只能使用单引号,否则执行会报错,Sqoop 对引号是比较敏感的。

(3)举例来说,假设我们将数据导入 HDFS 后最终是希望在 Hive 中进行查询,那么久可以使用 "\N" 表示 NULL值。因为 Hive 对于NULL 值在底层数据文件中是使用 “\N” 存储的。
sqoop import \
--connect jdbc:mysql://192.168.60.1:3306/hangge?serverTimezone=UTC \
--username root \
--password hangge1234 \
--target-dir /out3 \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by '\t' \
--query 'select id,name,phone from user where id >1 and $CONDITIONS;' \
--null-string '\\N' \
--null-non-string '\\N'

(4)上面任务执行完毕后,可以看到 HDFS 文件中数据的 NULL 值都被替换成 \N

5,封装 Sqoop 脚本

(1)在工作中使用 Sqoop 时,建议将 Sqoop 的命令写在 Shell 脚本中,否则无法实现命令重用,并且调用也不方便。比如,我们执行如下命令创建一个在 Shell 脚本:
vi sqoop-import-user.sh

(2)脚本内容如下:
#!/bin/bash
sqoop import \
--connect jdbc:mysql://192.168.60.1:3306/hangge?serverTimezone=UTC \
--username root \
--password hangge1234 \
--target-dir /out3 \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by '\t' \
--query 'select id,name,phone from user where id >1 and $CONDITIONS;' \
--null-string '\\N' \
--null-non-string '\\N'

(3)使用时执行如下命令即可:
./sqoop-import-user.sh

附:Sqoop 常见参数

1,通用参数

参数 解释
--connect <jdbc-uri> 指定 JDBC 连接字符串
--connection-manager <class-name> 指定要使用的连接管理器类
--driver <class-name> 指定要使用的 JDBC 驱动类
--hadoop-mapred-home <dir> 指定 HADOOP_MAPRED_HOME 路径
--help 帮助
--password-file 设置用于存放认证的密码信息文件的路径
-P 从控制台读取输入的密码
--password <password> 设置认证密码
--username <username> 设置认证用户名
--verbose 打印详细的运行信息
--connection-param-file <filename> 指定存储数据库连接参数的属性文件

2,数据导入相关参数数

参数 解释
--append 将数据追加到 HDFS 上一个已存在的数据集中
--as-avrodatafile 将数据导入 Avro 数据文件
--as-sequencefile 将数据导入 SequenceFile
--as-textfile 将数据导入普通文本文件(默认)
--boundary-query <statement> 边界查询,用于创建分片(InputSplit
--columns <col,col,col…> 从表中导出指定的一组列的数据
--delete-target-dir 如果指定目录存在,则先将其删除
--direct 使用直接导入模式(优化导入速度)
--direct-split-size <n> 指定切分输入数据的大小(在直接导入模式下)
--fetch-size <n> 从数据库中批量读取记录数
--inline-lob-limit <n> 设置内联的 LOB 对象的大小
-m,--num-mappers <n> 使用 n map 任务并行导入数据
-e,--query <statement> 导入的查询语句
--split-by <column-name> 指定按照哪个列去切分数据
--table <table-name> 导入的源表表名
--target-dir <dir> 导入 HDFS 的目标路径
--warehouse-dir <dir> HDFS 存放表的根路径
--where <where clause> 指定导出时所使用的查询条件
-z,--compress 启用压缩
--compression-codec <c> 指定 Hadoop 的压缩方式(默认为 Gzip
--null-string <null-string> 使用指定字符串,替换字符串类型值为 null 的列
--null-non-string <null-string> 使用指定字符串,替换非字符串类型值为 null 的列

3,数据导出相关参数数

参数 解释
--direct 使用直接导出模式(优化速度)
--export-dir <dir> 导出过程中 HDFS 的源路径
--m,--num-mappers <n> 使用 nmap 任务并行导出
--table <table-name> 导出的目的表名称
--call <stored-proc-name> 导出数据调用的指定存储过程名
--update-key <col-name> 更新参考的列名称,多个列名之间使用逗号分隔
--update-mode <mode> 指定更新策略,包括 updateonly(默认)、allowinsert
--input-null-string <null-string> 使用指定字符串,替换字符串类型值为 null 的列
--input-null-non-string <null-string> 使用指定字符串,替换非字符串类型值为 null 的列
--staging-table <staging-table-name> 在数据导出到数据库之前,数据临时存放的表名称
--clear-staging-table 清除工作区中临时存放的数据
--batch 使用批量模式导出
评论

全部评论(0)

回到顶部