Sqoop的使用

1. 简介

sqoop可以将一个关系型数据库(例如 : MySQL ,Oracle ,Postgres等)中的数据导进到Hadoop的HDFS中,也可以将HDFS的数据导进到关系型数据库中。

sqoop分为sqoop和sqoop2,但是sqoop2不兼容sqoop,且特征不完整,它并不打算用于生产部署。所以我们一般使用sqoop即可

Sqoop的原理是讲命令翻译为MR执行,MR没有Reduce阶段,只有Map阶段!

2. Sqoop的安装

2.1 官网下载安装包,上传解压,并配置环境变量

2.2 导入jar包

我们测试时将mysql的数据导入到HDFS,所以sqoop需要mysql的jar包( mysql-connector-java-5.1.46.jar)jar包可以去maven仓库上下载

2.3 测试

sqoop list-databases --connect jdbc:mysql://hadoop101:3306/ --username root --password 123456

执行命令,如果如果有错就说明成功了

3. 导入数据

在Sqoop中,“导入”概念指:从非大数据集群(RDBMS)向大数据集群(HDFS,HIVE,HBASE)中传输数据

3.1 mysql导入到HDFS

// \代表在shell窗口中换行
sqoop import \
// 连接的url
--connect jdbc:mysql://hadoop101:3306/company \
// 用户名
--username root \
// 密码
--password 123456 \
// 要导哪个表的数据
--table staff \
// 将数据导入到hdfs的哪个路径
--target-dir /company \
// 如果目标目录存在就删除
--delete-target-dir \
// 导入到hdfs上时,mysql中的字段使用\t作为分隔符
--fields-terminated-by "\t" \
// 设置几个MapTask来运行
--num-mappers 2 \
// 基于ID列,将数据切分为2片,只有在--num-mappers>1时才需要指定,选的列最好不要有null值,否则null
// 是无法被导入的!尽量选取主键列,数字列
--split-by id
// 只导入id和name 列
--columns id,name \
// 只导入复合过滤条件的行
--where 'id >= 10 and id <= 20' \
// 执行查询的SQL,讲查询的数据进行导入,如果使用了--query,不加再用--table,--where,--columns
// 只要使用--query ,必须添加$CONDITONS,这个条件会被Sqoop自动替换为一些表达式
--query "SQL"

3.1.1 示例1

sqoop import \
--connect jdbc:mysql://hadoop101:3306/company \
--username root \
--password 123456 \
--table staff \
--target-dir /staff \
--delete-target-dir \
--fields-terminated-by "\t" \
--num-mappers 2 \
--split-by id \
// 不加下面两行就是全部导入,加了就导入10>=id>=5的数据,且只导入age,name两列
--columns age,name \
--where 'id >= 5 and id <= 10'

3.1.2 根据sql语句导入部分数据

bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/mydb \
--username root \
--password 123456 \
--query "select * from t_emp where \$CONDITIONS and id >=2" \
--target-dir /t_emp \
--delete-target-dir \
--fields-terminated-by "\t" \
--num-mappers 2 \
--split-by id

注意点:

1. query后面的sql语句要用引号引起来,否则在shell中空格代表参数分割。如果query后使用的是双引号,则$CONDITIONS前必须加转移符,防止shell识别为自己的变量。

2. 一定要加上$CONDITIONS,原因:由于设定了多个maptask, 而每个maptask都只会导入的一部分数据,$CONDITIONS在sql执行时会自动替换为一些参数,来区分A maptask执行哪些数据,B maptask执行哪些数据

3.2 mysql导入到Hive

Sqoop导入到hive,先讲数据导入到HDFS,再将HDFS的数据,load到hive表中!

/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 123456 \
--table staff \
--num-mappers 1 \
//导入到hive
--hive-import \
//导入到hive表中字段的分隔符
--fields-terminated-by "\t" \
// 是否以insert overwrite方式覆盖导入数据
--hive-overwrite \
// 要导入的hive表的名称,会自动帮助我们建表。建议还是在hive中手动建表,需要注意和mysql表的数据类型匹配
--hive-table staff_hive

3.2.1 示例

sqoop import \
--connect jdbc:mysql://hadoop102:3306/mydb \
--username root \
--password 123456 \
--table t_emp \
--num-mappers 1 \
--hive-import \
--fields-terminated-by "\t" \
--hive-overwrite \
--hive-table t_emp

3.3 mysql数据导入到Hbase

sqoop import \
--connect jdbc:mysql://hadoop101:3306/company \
--username root \
--password 123456 \
--table staff \
--where 'id <= 5' \
--hbase-create-table \
--hbase-table "staff_hbase" \
--hbase-row-key "id" \
--column-family "info" \
--num-mappers 1 \
--split-by id;

 3.3.1 报错解决

Exception in thread "main" java.lang.NoSuchMethodError: org.apache.hadoop.hbase.client.HBaseAdmin.<init>(Lorg/apache/hadoop/conf/Configuration;)V

当报以上错误的时候,是说hbase版本太高或太低导致缺少了部分类,所以此时我们需要向sqoop的lib目录下放入一些hbase的jar包,注意我本地安装的hbase版本是2.4.5的,偏高,所以不能直接将hbase的lib目录下的hbase相关jar包直接放到sqoop下,需要重新下一个低版本的hbase,我这里亲测1.3.5版本的hbase是可以的。

1.  在hbase官网上重新下载一个1.3.5版本的安装包

2. 将这个hbase安装包解压,并将其中部分jar包复制到sqoop的lib目录下,需要复制到sqoop的jar包如下图所示:

3. 运行导入语句,发现就可以正常导入了

当然最好的还是在安装hbase集群时,将hbase版本定为1.3.5

3.3.2 sqoop是否只能将数据导入本地的hbase?

sqoop安装在A机器,hbase和zk分别在A,B,C三台机器都存在,并且是集群模式,此时,我强制关闭了A机器的hbase和zk服务,再导入数据到hbase,结果发现,数据依然能成功导入到hbase,所以得出结论sqoop可以导入数据到hbase集群:

因为sqoop会默认读取主机的环境变量,只要你配置了hbase和zk的全局环境变量,那么就算本机的hbase和zk挂了,sqoop依然能读取到zk的集群的配置,进而获取hbase的集群信息

4. 导出

在Sqoop中,“导出”概念指:从大数据集群(HDFS,HIVE)向非大数据集群(RDBMS)中传输数据

sqoop export \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 123456 \
//要导出的mysql的表名
--table staff2 \
--num-mappers 1 \
//导出的数据在hdfs上的路径
--export-dir /company \
// 导出时,基于哪一列判断数据重复
--update-key xx
// 导出数据时,如果主键重复,使用哪种模式
--update-mode
// 导出的数据的分隔符
--input-fields-terminated-by "\t"

 4.1 HDFS导出到mysql示例

sqoop export \
--connect 'jdbc:mysql://hadoop101:3306/company?useUnicode=true&characterEncoding=utf-8' \
--username root \
--password 123456 \
--table staff \
--num-mappers 1 \
--export-dir /staff \
--update-key id \
--update-mode  allowinsert \
--input-fields-terminated-by "\t";

在mysql中执行插入时,如果对于某些唯一列,出现了重复的数据,那么会报错Duplicate Key!
此时,对于重复的列,如果希望指定更新其他列的操作,通俗的讲,就是主键不存在即新增,存在即更新。那么可以使用以下写法:

INSERT INTO t_emp2 VALUE(6,'jack',30,3,100001) ON DUPLICATE KEY UPDATE
NAME=VALUES(NAME),age=VALUES(age),deptid=VALUES(deptid),empno=VALUES(empno);

在执行export导出时,默认的导出语句适用于向一个新的空表导数据的场景!每一行要导出的记录,都会转换为Insert语句执行查询,此时如果说触犯了表的某些约束,例如主键唯一约束,此时Insert失败,Job失败!

如果希望遇到重复的数据,就更新,不重复的数据就新增导入,可以使用--update-key,结合
--update-mode(默认为updateonly)=allowinsert。

4.2 HBase中数据导入到MySQL中

目前没有命令可以直接将 hbase 中的数据导出到 mysql,原因:hbase是大数据生态圈的组件,就是为了存放大数据,直接导出到MySQL,MySQL是否可以承受这么大的压力?

替代方案:

  1. 先将 hbase 的数据导出到 hdfs,然后再把数据从HDFS导入MySQL中
  2. 把Hbase表映射为hive表,然后把hive表中数据导出到MySQL中

5. 脚本

1. 创建一个.opt文件

touch opt/job_mysql2hdfs.opt

2. 编写脚本

import
--connect
jdbc:mysql://hadoop102:3306/company
--username
root
--password
123456
--table
staff
--target-dir
/company3
--delete-target-dir
--num-mappers
1
--fields-terminated-by
"\t"
--split-by

3.执行该脚本

sqoop --options-file 脚本路径
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

巴中第一皇子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值