sqoop是apache旗下一款“Hadoop和关系数据库服务器之间传送数据”的工具,除此之外还有DataX。
导入数据: MySQL,Oracle导入数据到Hadoop的HDFS、HIVE、HBASE等数据存储系统;
导出数据: 从Hadoop的文件系统中导出数据到关系数据库。
底层工作机制:
将导入或导出命令翻译成 MapReduce 程序来实现,
在翻译出的 MapReduce 中主要是对 InputFormat 和 OutputForm。
Cloudera Manager 支持的版本为 Sqoop 2。
一、添加sqoop2到CDH
因为我使用的的CDH搭建hadoop集群,所以可以通过cloudera manager添加上sqoop2.
二、把Oracle驱动拷贝到Sqoop安装路径中的lib文件夹下
我的ORACLE 是10G ,找到ojdbc6.jar,放到sqoop 的lib 下面,目录是
/opt/cloudera/parcels/CDH-5.10.0-1.cdh5.10.0.p0.41/lib/sqoop/lib
/opt/cm-5.10.0/share/cmf/lib/ojdbc6.jar
/var/lib/sqoop2/ojdbc6.jar
三、oracle全量数据导入到hdfs
1、root 用户执行:
sudo -u hdfs hadoop fs -mkdir /data/zhao/
在hdfs的data下,创建一个zhao文件夹
2、切换到hdfs 用户:
su hdfs
执行 export ACCUMULO_HOME=/data
3、执行import操作
sqoop import --connect jdbc:oracle:thin:@192.168.183.251:1521:YJDSJ --username yjdsj --password yjdsj#123 --table T_LOADS_TODAY --target-dir /data/zhao/heng --m 1 --columns obj_id,today_load,dept_id
说明:
导入的目录若已经存在则要先删除已经存在的目录,否则会报路径以存在的错误提示:
FileAlreadyExistsException: Output directoryhdfs://master:8020/user/operate already exists | |
---|---|
所以 /data/zhao/heng 这个目录是不存在的
**hdfs 用户执行该命令删除目录 : **
hadoop fs -rm -r /data/zhao/heng
4、查看
当出现这个页面,表示导入成功
访问HDFS:http://192.168.43.36:50070/
四、定时增量导入
数据全量导入到hdfs后,每隔一段时间oracle又会出现新的数据,此时不可能再将所有数据重新导一遍,我们就需要增量数据导入这一模式了。
sqoop支持两种增量导入模式:
1、append:只有新增数据
比如订单表,每个订单有一个唯一标识自增列ID,在关系型数据库中以主键形式存在。之前已经将id在0~100之间的编号的订单导入到这里为HDFS,现在一段时间后我们需要将近期产生的新的订单数据导入HDFS,以供后续数仓进行分析。此时我们只需要指定–incremental 参数为append,–last-value参数为100即可。表示只从id大于100后开始导入。
参数 | 说明 |
---|---|
–incremental append | 基于递增列的增量导入(将递增列值大于阈值的所有数据增量导入Hadoop) |
–check-column | 递增列(int) |
–last-value | 阈值(int) |
例如: sqoop import \
--connect jdbc:mysql://h3:3306/ry \
--username root \
--password haitao.211123 \
--table doit_jw_stu_zsgl \
--hive-import \
--hive-table yiee_dw.doit_jw_stu_zsgl \
--split-by id \
--incremental append \
--check-column id \
--last-value 40 \
-m 2
2、lastmodified : 包含修改和新增数据
此方式要求原有表中有time字段,它能指定一个时间戳,让Sqoop把该时间戳之后的数据导入至HDFS。因为后续订单可能状态会变化,变化后time字段时间戳也会变化,此时Sqoop依然会将相同状态更改后的订单导入HDFS,当然我们可以指定merge-key参数为pid,表示将后续新的记录与原有记录合并。
参数 | 说明 |
---|---|
–incremental append | 基于时间列的增量导入(将时间列大于等于阈值的所有数据增量导入Hadoop) |
–check-column | 时间列(int) |
–last-value | 阈值(int) |
–merge-key | 合并列(主键,合并键值相同的记录) |
例如: sqoop import \
--connect jdbc:mysql://h3:3306/ry \
--username root \
--password haitao.211123 \
--table doit_jw_stu_zsgl \
--target-dir '/sqoopdata/doit_jw_stu_zsgl' \
--incremental lastmodified \
--check-column update_time \
--last-value '2020-03-18 23:59:59' \
--fields-terminated-by ',' \
-m 1 \
因为我的表中,pid为随机产生的32位数字,所以选择使用lastmodified 。
执行导入:
sqoop import --connect jdbc:oracle:thin:@10.68.24.80:1521:YJDSJ --username yjdsj --password yjdsj#123 --table T_POWERGRID_DAMAGE_FORECAST --target-dir /data/06/02 --m 1 --incremental lastmodified --check-column CREATE_DATE --merge-key pid --last-value '2018-6-12 11:00:00'
若定时增量导入,则需要创建一个job
sqoop job --create dashuju -- import --connect jdbc:oracle:thin:@10.68.24.80:1521:YJDSJ --username yjdsj --password yjdsj#123 --table T_POWERGRID_DAMAGE_FORECAST --target-dir /data/06/02 --m 1 --incremental lastmodified --check-column CREATE_DATE --merge-key pid --last-value '2018-6-12 11:00:00'
使用crontab定时器
crontab -e
增加定时任务(每35分钟执行一次)
*/35 * * * * sqoop job --exec dashuju
重启crontab定时器
service crond start
期间启动了多个定时任务,曾报maxContainerCapability 设置不足
异常:
REDUCE capability required is more than the supported max container capability in the cluster. Killing the Job. reduceResourceRequest: <memory:12160, vCores:1> maxContainerCapability:<memory:8192, vCores:24>
需要调整两个参数:
yarn.nodemanager.resource.memory-mb
yarn.scheduler.maximum-allocation-mb
每次执行sqoop job时,会提示输入密码,如何避免呢?
====修改配置文件====
vi /etc/sqoop/conf/sqoop-site.xml
<property>
<name>sqoop.metastore.client.record.password</name>
<value>true</value>
<description>If true, allow saved passwords in the metastore.
</description>
</property>
五、hdfs导出到oracle
export工具,是将HDFS平台的数据,导出到外部的结构化存储系统中,可能会为一些应用系统提供数据支持.
全量导出
sqoop export --connect jdbc:oracle:thin:@10.68.24.80:1521:YJDSJ --username yjdsj --password yjdsj#123 --table T_POWERGRID_DAMAGE_FORECAST --export-dir /data/06/03/part-m-00000 --input-fields-terminated-by ',' --input-null-string 'null' --input-null-non-string 'null' -m 1 --batch
此方式要求导出的oracle数据库中的表为空表或者新表,不然新的数据产生,再次导出的时候,会违反主键唯一的约束,可以使用以下的命令:
更新模式
sqoop export --connect jdbc:oracle:thin:@10.68.24.80:1521:YJDSJ --username yjdsj --password yjdsj#123 --table T_POWERGRID_DAMAGE_FORECAST --export-dir /data/06/03/part-m-00000 --input-fields-terminated-by ',' --input-null-string 'null' --input-null-non-string 'null' -m 1 --update-mode allowinsert --update-key PID --batch
–update-mode < mode > 指定更新策略,包括:updateonly(默认)、allowinsert;
如果选择updateonly,只会对mysql中已存在的id数据进行更新,不存在的id数据不会插入了;
如果选择allowinsert,既会更新已存在id数据,也会插入新的id数据
–update-key < col-name > 更新参考的列名称,多个列名使用逗号分;
sqoop使用手册参考:
https://www.cnblogs.com/xiaodf/p/6030102.html#431