“ 这是尼萌工作室的第【 9】篇文章。本文正文1830字,阅读完成约5分钟。”
说明:目前有sqoop 1和sqoop 2 两个版本,两者不兼容。本文描述对象为sqoop1,若对sqoop2有兴趣的童鞋可到官网查阅。
01 初识Sqoop
—
Sqoop 是连接传统关系型数据库(支持JDBC的Connector)和 Hadoop 生态系统的桥梁。采用批处理的方式,利用MR 来加快数据传输速度,完成数据传输。
Sqoop 是一个客户端工具,它的架构非常简单的,主要由三个部分组成:Sqoop client、HDFS/HBase/Hive、Database 。
02 RDB数据导入HDFS
—
将数据从传统数据库导入HDFS分为两步:
- 步骤1: Gather Metadata
Sqoop与数据库server通信 ,获取数据库表元数据信息;
完成并发数设定,字段类型如何映射,如何转化等任务。
- 步骤2: Submit Map-Only Job
Sqoop启动Map-Only 的MR作业,并行导入元数据。
全量数据导入
全量导入适合一次性导入做离线分析。
sqoop import \ --connect jdbc:mysql://ip:port/db \ --username root \ --password pass \ --table users \ --target-dir /user/root/ users_all \ --null-string "\\N" \ --null-non-string "\\N" \
重要参数说明:
参数 | 说明 |
--query | 导入的查询语句,不能和--table 同时使用。 select * from table where \$CONDITIONS” \ |
--table | 导入的源表表名 |
--target-dir | 导入HDFS的目标路径 |
--null-string | string类型空值的替换符 |
--null-non-string | 非string类型空值的替换符 |
-m | map 任务数量,默认为4。 |
--split-by | 若map任务数>1, 需要指定根据哪一列来实现哈希分片,从而将不同分片的数据分发到不同map 任务上去跑,避免数据倾斜。 |
增量数据导入
在实际生产环境中,系统可能会定期从与业务相关的关系型数据库向Hadoop导入数据,导入数仓后进行后续离线分析。故我们此时不可能再将所有数据重新导一遍,此时就需要增量数据导入这一模式了。
增量数据导入分两种:1.基于递增列的增量数据导入。2.基于时间列的增量数据导入。
- 基于递增列的增量数据导入
将递增列值大于阈值的所有数据增量导入Hadoop。采用append 方式,每次运行增量导入到表之前,都要修改--last-value的值,否则出现重复记录。同时也要求源表中ID为递增且不重复。
重要参数说明:
参数 | 说明 |
--incremental append | 基于递增列的增量导入 |
--check-column | 指定递增列,int类型 |
--last-value | 起始导入的阈值,int类型 |
? 用户表中有一个自增列ID,之前已将ID号为0~999的用户数据导入到HDFS,后续只需要只从ID大于999后开始导入即可。
- 基于时间列的增量数据导入
将时间列值大于阈值的数据增量导入Hadoop。该方式要求原来表中存在time 字段。
重要参数说明:
参数 | 说明 |
--incemental lastmodified | 给予时间列的增量导入 |
--check-column | 时间列,int 类型 |
--last-value | 起始导入的阈值,如'2020-01-01 10:00:00' |
--merge-key | 合并列,合并键值相同记录,一般指主键 |
? 用户的常住地发生变化,修改用户信息表,update_time 字段也随之改变,Sqoop依然会将相同状态更改后的用户信息导入HDFS。此时HDFS将出现两条同一用户的数据,我们可以指定merge-key参数为user_id,将新的记录与原有记录合并。
03 RDB数据导入Hadoop其他系统
—
除了HDFS,Sqoop还能与Hadoop其他系统良好的交互。如Hive,Hbase。
Sqoop import 到Hive 表
若导入的Hive表不存在,则create,反之则直接导入到表的文件目录。
⭐️1.原关系型数据库字符串存在\n, \r, and \01 等特殊字符,不处理会出现导入hive表字段错位情况(摔过大跟斗),可以设置以下参数去除、替换 特殊字符
- --hive-drop-import-delims 导入到hive时删除 \n, \r, and \01
--hive-delims-replacement 导入到hive时用自定义的字符替换掉 \n, \r, and \01
⭐️ 2.Sqoop不支持hive自定义分隔符如\u001,\001,建表时应避免使用。
sqoop import \--connect jdbc:mysql://ip:port/db \--username root \--password pass \ --table users \ --target-dir /user/root/users_all \ --hive-import--hive-drop-import-delims \-m 1 \--fields-terminated-by "\t" \--lines-terminated-by "\n"
Sqoop import 到Hbase 表
Hbase 无法自动创建表,因此Hbase表不存在时先创建。
sqoop import \ --connect jdbc:mysql://ip:port/db \ --username root \ --password pass \ --table users \ --target-dir /user/root/ users_all \ --hbase-table users \ --column-family info
04 Sqoop 导出HDFS数据至RDB
—
导出的步骤跟导入差不多,也分两步,篇幅有限,便不再展开。
- 步骤1: Gather Metadata
Sqoop与数据库server通信 ,获取数据库表元数据信息;
完成并发数设定,字段类型如何映射,如何转化等任务。
- 步骤2: 并行导出数据
将Hadoop上文件划分成若干split,每个split由一个Map task 导入数据。
sqoop export \ --connect jdbc:mysql://ip:port/db \ --username root \ --password pass \ --table users \ --export-dir /user/root/ users_all
重要参数说明:
参数 | 说明 |
--export-dir | 数据的存放目录 |
05 Sqoop 密码保护
—
安全机制不够完善,例如密码暴露是Sqoop1的缺陷之一。我们可以通过下面两种方式规避这种风险。
- -P
命令行最后使用-P,此时提示用户输入密码,而且用户输入的密码是看不见的,起到安
全保护作用。密码输入正确后,才会执行sqoop 命令。但该方法每次启动Sqoop任务都需要输入密码,对例行化任务不友好。
sqoop import \--connect jdbc:mysql://ip:port/db \--username root\--table user \-P
- –password-file
指定一个密码保存文件,读取密码。我们可以将这个文件设置为只有自己可读的文件,防止密码泄露。
sqoop import \--connect jdbc:mysql://ip:port/db \--username root \--table user \--password-file my-sqoop-password
reference
- Sqoop 官方网站 http://sqoop.apache.org/
- END -
谁怕,一蓑烟雨任平生