Sqoop 是一个数据库数据导入导出工具
Sqoop 即 sql + hadoop
Sqoop执行时,底层使用的MR中的map,所以输出文件的名字都是part-m
sqoop底层默认开启4个map任务,所以如果不指定的话就默认有四个文件
sqoop分割也不是按照平均分割的,而是根据主键的值,除以 4 份 (默认分割四个文件)根据每一份的跨度进行文件中值的存入
Sqoop的核心设计思想是利用MapReduce加快数据传输速度。也就是说Sqoop的导入和导出功能是通过基于Map Task(只有map)的MapReduce作业实现的。所以它是一种批处理方式进行数据传输,难以实现实时的数据进行导入和导出。
所以要想使用sqoop,需要启动 hdfs 和 yarn
MySQL: 关系型数据库 (Oracle, SQL Server, DB2 ) -- 业务数据 HDFS: 海量数据存储(文件类型的)分布式文件存储系统 Hive: 数据分析工具(将SQL翻译为MR) HBase: 非关系型数据库(NoSQL) 学习的Redis Sqoop 是一个数据导入导出工具,可以将MySQL的数据导入到HDFS,Hive,Hbase中。 也可以将HDFS,Hive 中的数据导出到mysql。 Sqoop 底层也是使用的MapReduce 中的Map
sqoop 导出
import 命令
将mysql的emp这个表的数据导入到hdfs上:
sqoop import \
--connect jdbc:mysql://bigdata01:3306/sqoop \
--driver com.mysql.cj.jdbc.Driver \
--username root \
--password 123456 \
--table emp \
--target-dir /home \
--delete-target-dir
将mysql的数据导入到HDFS
sqoop表中也可以添加where判断条件,同时也可以使用sql语句
使用sql语句时,需注意:
若需要使用sql, --query 就需要在sql语句的后面 加上 and $conditions,而且必须和split-by 一起使用
-m 1 -------> 将结果只显示到一个文件中
关于split-by的一个问题 :
如果切割的字段不是int类型的 而是string类型的
直接切割的话会报错
解决办法: 在import 后面加上这句话即可
sqoop import "-Dorg.apache.sqoop.splitter.allow_text_splitter=true" \
解决:
第一种方案:进入sqoop的lib下面
运行如下代码:
配置中需要添加--bindir ./
sqoop import --bindir ./
--connect jdbc:mysql://localhost:3306/db
--username root
--password 123456
--table user
-m 1
第二种解决办法: 将如下内容添加到环境变量中 /etc/profile export SQOOP_CLASSPATH=/opt/installs/sqoop/lib
MySQL数据导入到Hive (sqoop特有)
sqoop import --connect jdbc:mysql://bigdata01:3306/sqoop \
--driver com.mysql.cj.jdbc.Driver \
--username root \
--password 123456 \
--table emp \
--hive-import \
--hive-overwrite \
--hive-table emp \
--hive-database yhdb \
-m 1
第一次执行mysql导入hive的时候,也会出现错误,即jar包缺失问题,拷贝一下或者配置环境即可
cp /usr/local/hive/lib/hive-exec-3.1.2.jar /usr/local/sqoop/lib/---此包暂时不拷贝 cp /opt/installs/hive/lib/hive-common-3.1.2.jar /opt/installs/sqoop/lib
再次执行,还是报错,假如显示 。。。。已存在
把 它删了就可以了
注意:
hive数据库需要提前存在,否则错误
但是表可以不需要提前存在, 如果不存在的话会自动创建
增量导入:
什么是全量,什么是增量
全量导入: 一次性将一个数据库的所有数据,导入到另一个地方。
增量导入:每次导入的时候只需要将新增的数据导入到另一个地方即可。
一般的做法是:第一次全量导入,后面每隔一段时间进行一次增量导入。
通过last_value实现:
sqoop import --connect jdbc:mysql://bigdata01:3306/yhdb \
--username root \
--password 123456 \
--table sales_order \
--driver com.mysql.cj.jdbc.Driver \
--target-dir /home/sales_order/dt=202402 \
-m 1 \
--check-column orderId \
--incremental append \
--last-value 0 \
--fields-terminated-by '\t'
注意:要想使用last-value 实现增量导入 就必须写--check-column XX (xx多为主键)--incremental append
优点:不需要依赖日期字段
缺点:每次导入之后都要记录last-value的值。
Sqoop的导出
从hdfs 导出到mysql
Export
sqoop export \
--connect jdbc:mysql://bigdata01:3306/sqoop \
--username root \
--password 123456 \
--table user \
--export-dir '/home/a.txt' \
--input-fields-terminated-by ',' \ -- 指定分隔符
--columns 'id,age' \ -- 指定字段
-m 1
将hdfs 导出到mysql 的时候, sql中的表需要提前创建出来
!从hive导出到mysql*
将hive表中的数据导入mysql中:
sqoop export \
--connect jdbc:mysql://bigdata01:3306/sqoop \
--username root \
--password 123456 \
--table user3 \
--hcatalog-database sqoop \
--hcatalog-table par3 \
-m 1
执行以上脚本后,可能会出现错误:
只需要在sqoop-env.sh 中 添加 export HCAT_HOME=/opt/installs/hive/hcatalog 即可。
Sqoop中的Job任务
创建job任务好处:
1、可以将经常使用的导入导出脚本,编写为job任务,每次执行一下命令即可
2、可以帮助我们记录last-value,从而更好的利用last-value进行增量导入
sqoop job --create jjoobb -- import --connect jdbc:mysql://bigdata01:3306/sqoop \
--username root \
--password 123456 \
--table user \
--delete-target-dir \
--target-dir '/sqoop/user' \
-m 1
第一次执行job任务的时候,会报空指针异常
此时,问题其实是jar包缺失问题,只需要在sqoop/lib 下,拷贝一个 java-json的jar包即可
sqoop job --create jod的名字 -- 创建job
sqoop job --list -- 查看job
sqoop job --delete job的名字 -- 删除job
sqoop job --exec job的名字 -- 执行job
使用Job任务实现增量导入
我们在使用上面的last-value完成增量导入的时候,需要在执行的时候记得last-value的值,
通过last-value的增量导入代码,实现一个job任务既可以不需要记得即可:
创建job任务:
sqoop job --create auto_import -- import --connect jdbc:mysql://bigdata01:3306/sqoop \
--username root \
--password 123456 \
--table sales_order \
--driver com.mysql.cj.jdbc.Driver \
--target-dir /home/sales_order/dt=20240903 \
--split-by orderId \
-m 1 \
--check-column orderId \
--incremental append \
--last-value 0 \
--fields-terminated-by '\t'
执行:
sqoop job --exec auto_import
结果如下