一、聊概念

  1. Sqoop就是将数据从MySQL导入到hdfs,hive,hbase中,从hdfs,hive中导出到mysql 的工具,底层使用的技术是MapReduce中的map
  2. MySQL有啥优势:执行效率很高,数据也很安全(支持事务)。
  3. HDFS:存储海量数据(文件)
  4. Hive:可以分析海量数据(N+1

image.png

Sqoop的重要的几个关键词

- ==import== : 从关系型数据库到Hadoop
- ==export== : 从Hadoop到关系型数据库。

二、安装Sqoop

第一步:上传,解压到 /usr/local

tar -xvf sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz -C /usr/local

第二步:修改名字

cd /usr/local;
mv  解压的包名  sqoop

第三步:修改环境变量 /etc/profile

使用notepad++
export SQOOP_HOME=/usr/local/sqoop
export PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/sbin:$HADOOP_HOME/bin:$ZOOKEEPER_HOME/bin:$HIVE_HOME/bin:$SQOOP_HOME/bin

第四步:刷一下环境变量

source /etc/profile

第五步:修改配置文件

进入到sqoop的家目录下的conf下
复制一份配置文件
cp sqoop-env-template.sh sqoop-env.sh
修改sqoop-env.sh
export HADOOP_COMMON_HOME=/usr/local/hadoop
export HADOOP_MAPRED_HOME=/usr/local/hadoop
export HIVE_HOME=/usr/local/hive
export ZOOCFGDIR=/usr/local/zookeeper

第六步:拷贝mysql的驱动包
image.png
不是安装包

将我们的驱动包,存放到 sqoop的lib目录下一份

第七步:验证是否成功 sqoop version
image.png
没有配置这个,留下了一个问题,随后再说:
image.png

三、sqoop的操作

1、常见的命令 sqoop help

image.png

2、直接执行命令

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

image.png
如果存在以下错误:
image.png
这种类型的错误,一看就是缺包。
缺少的是common-lang 这个jar包。

find / -name commons-lang-2.6.jar

将我们查找到的jar包拷贝一份到sqoop的lib下:
cp /usr/local/hive/lib/commons-lang-2.6.jar ./     ./表示的是当前路径下
也可以
cp /usr/local/hive/lib/commons-lang-2.6.jar /usr/local/sqoop/li概念

3、通过文件运行 命令

我们也可以将经常使用的命令,存储为文件,想运行的时候直接运行即可。

在sqoop中,我们可以创建文件
mkdir laoyansqoop
cd laoyansqoop
编辑  mysqllink.conf

# 这个是展示所有数据库的命令
list-databases
--connect
jdbc:mysql://192.168.32.100:3306
--username
root
--password
123456


进行保存,执行即可
sqoop --options-file mysqllink.conf

四、导入Import

mysql —> HDFS mysql —>Hive mysql—>HBase

4.3.4.1 通用参数

如下:

Argument Description
==—connect== 指定JDBC连接字符串
—connection-manager 指定连接管理类
—driver 指定连接的驱动程序
-P 从控制台读入密码(可以防止密码显示中控制台)
==—password== 指定访问数据库的密码
==—username== 指定访问数据库的用户名

第一个查看所有表:

sqoop list-tables --connect jdbc:mysql://localhost:3306/mydb --username root --password 123456

import 中 常用参数:

Argument Description
—append 通过追加的方式导入到HDFS
—as-avrodatafile 导入为 Avro Data 文件格式
—as-sequencefile 导入为 SequenceFiles文件格式
—as-textfile 导入为文本格式 (默认值)
—as-parquetfile 导入为 Parquet 文件格式
—columns 指定要导入的列
—delete-target-dir 如果目标文件夹存在,则删除
—fetch-size 一次从数据库读取的数量大小
-m,—num-mappers m 用来指定map tasks的数量,用来做并行导入
-e,—query 指定要查询的SQL语句
—split-by 用来指定分片的列
—table 需要导入的表名
—target-dir HDFS 的目标文件夹
—where 用来指定导入数据的where条件
-z,—compress 是否要压缩
—compression-codec 使用Hadoop压缩 (默认是 gzip)

第一个案例:从mysql中导入数据hdfs
mysql中先有数据:
新建数据库
image.png
导入一些数据:
此处省略mysql导入sql脚本的演示。
编写导入命令:

sqoop import --connect jdbc:mysql://localhost:3306/qfdb \
--username root --password 123456 \
--table emp \
--target-dir hdfs://bigdata01:9820/sqoopdata/emp \
--delete-target-dir

总结:

导入要使用 import 
要进行数据库连接
--table 可以指定要导入的表
--target-dir   表的数据要导入到hdfs哪个位置
--delete-target-dir  如果之前导入过,删除目标文件
每一行后面空格一下,输入一个  \  表示该命令没有写完,换行了。

解释疑问:
1、为什么是4个?
image.png
这个是默认的配置,会将我们mysql中的数据按照主键,进行切分,切分为4份。
image.png
它不是按照数据的条数/4 进行平均分配的。
image.png
2、为什么不是平均分配?
它是先求出主键的最大值,主键的最小值,最大值-最小值/4 = 跨度。
7934-7369=565 565 / 4 = 141 左右
image.png
3、为什么是 part-m-00000 ?

我们的sqoop 本质是mapreduce中的map任务,map任务的输出就是 part-m-xxxxx

4、为什么报错?
image.png
报错的原因是超时了,连接超时了。
mysql的连接超时时间,默认是8小时,可以修改为1天。
修改我们的 /etc/my.cnf 中的文件即可:

wait_timeout=31536000
interactive_timeout=31536000

添加完之后,要重启mysql服务

systemctl restart mysqld

以上这个案例,是将表中的数据全部导入hdfs,还可以根据条件进行筛选

sqoop import --connect jdbc:mysql://localhost:3306/qfdb \
--username root --password 123456 \
--table emp \
--columns 'empno,sal' \
--where 'empno>7800' \
--target-dir hdfs://bigdata01:9820/sqoopdata/emp5 \
--delete-target-dir

指定SQL语句进行导入(一般出现在sql语句比较复杂的情况)

sqoop import --connect jdbc:mysql://localhost:3306/qfdb \
--username root --password 123456 \
--query 'select empno,sal,mgr,job from emp where empno>7800 and $CONDITIONS' \
--target-dir hdfs://bigdata01:9820/sqoopdata/emp6 \
--delete-target-dir \
--split-by empno

image.png
如果通过sql语句进行导入,必须添加$CONDITIONS,必须指定 —split-by 字段,这个字段一般是主键。
我们也可以指定,我们的map任务只有一个,注意只有一个 - 是 -m

sqoop import --connect jdbc:mysql://localhost:3306/qfdb \
--username root --password 123456 \
--query 'select empno,sal,mgr,job from emp where empno>7800 and $CONDITIONS' \
--target-dir hdfs://bigdata01:9820/sqoopdata/emp7 \
--delete-target-dir \
--split-by empno \
-m 1

单引号和双引号的区别:

sqoop import --connect jdbc:mysql://localhost:3306/qfdb \
--username root --password 123456 \
--query "select empno,sal,mgr,job from emp where empno>7800 and \$CONDITIONS" \
--target-dir hdfs://bigdata01:9820/sqoopdata/emp7 \
--delete-target-dir \
--split-by empno \
-m 1

如果我们的mysql中的表中,没有主键,怎么办?
我们执行之前的sqoop语句:

sqoop import --connect jdbc:mysql://localhost:3306/qfdb \
--username root --password 123456 \
--table emp \
--columns 'empno,sal' \
--where 'empno>7800' \
--target-dir hdfs://bigdata01:9820/sqoopdata/emp8 \
--delete-target-dir

image.png
给出了两个方案,要么告诉我按照哪个字段切割,要么指定map任务只有一个(因为一个不牵涉切割的问题)

sqoop import --connect jdbc:mysql://localhost:3306/qfdb \
--username root --password 123456 \
--table emp \
--columns 'empno,sal' \
--where 'empno>7800' \
--target-dir hdfs://bigdata01:9820/sqoopdata/emp8 \
--delete-target-dir \
--split-by empno
-m 1

image.png
如果看到这个异常,说明任务执行失败了,但是也会执行成功一部分,所以我们还是可以看到hdfs上有部分数据。继续执行一遍。

第二个案例:将mysql 导入到 hive中

导入时,所使用的参数跟hdfs不一样,如下所示:
具体的参数如下:

Argument Description
—hive-home 覆盖环境配置中的$HIVE_HOME,默认可以不配置
—hive-import 指定导入数据到Hive中
—hive-overwrite 覆盖当前已有的数据
—create-hive-table 是否创建hive表,如果已经存在,则会失败
—hive-table 设置要导入的Hive中的表名

直接将mysql中的emp表导入到hive中:

sqoop import --connect jdbc:mysql://192.168.32.100:3306/qfdb \
--username root \
--password 123456 \
--table emp \
--hive-import \
--hive-overwrite \
--hive-table "emp2" \
--hive-database qfdb \
-m 1

image.png
出现了一个错误,这个错误就是缺包。

cp /usr/local/hive/lib/hive-exec-2.1.1.jar /usr/local/sqoop/lib/   ---此包暂时不拷贝
cp /usr/local/hive/lib/hive-common-2.1.1.jar /usr/local/sqoop/lib/

image.png
不需要提前在hive中建表。
image.png

增量导入(重要的):

增量导入的意思是,今天emp表中有1000万数据,进行一次全量导入,下一次导入的时候,只需要导入新增的那部分数据就可以了,不需要每次都全量导入。
第一种方式:通过查询的方式,增量导入
第二种方式:自增的方式,昨天导入到序号是1000的数据,我今天就导入1001开始的数据。

第一种方式:每天导入前一天的数据,因为命令都一样,只有日期不一样,所以我们可以将日期抽取出来,变为一个变量
编写一个mysql

create table sales_order(
   orderId int primary key,
   order_date date
)

编写一个脚本(shell脚本): import.sh
1 2022-01-10

#!/bin/bash
# 获取昨天的日期
# yesterday=`date -d "1 days ago" "+%Y-%m-%d"`
yesterday=$1
sqoop import --connect jdbc:mysql://localhost:3306/qfdb \
--username root --password 123456 \
--query "select * from sales_order where order_date='${yesterday}' and \$CONDITIONS" \
--target-dir hdfs://bigdata01:9820/sqoopdata/dt=${yesterday} \
--delete-target-dir \
-m 1 \
--fields-terminated-by '\t'

将这个脚本赋权限

chomd 777 import.sh
执行该脚本   ./import.sh 2022-04-18
我每天执行前一天的日期,达到一个增量导入的效果。

第二种实现增量导入的方式:
编写sqoop命令,通过一个—last-value 进行增量导入:

sqoop import --connect jdbc:mysql://bigdata01:3306/qfdb \
--username root \
--password 123456 \
--table sales_order \
--driver com.mysql.jdbc.Driver \
--target-dir hdfs://bigdata01:9820/sqoopdata/sales_order2/dt=2022 \
--split-by orderId \
-m 1 \
--check-column orderId \
--incremental append \
--last-value 0 \
--fields-terminated-by '\t'

第一次last-value开始导入,就是从第一条记录开始导入,第一次是全量的。
第二次的时候,一定要看信息,提示从哪个值开始,就写哪个?

sqoop import --connect jdbc:mysql://bigdata01:3306/qfdb \
--username root \
--password 123456 \
--table sales_order \
--driver com.mysql.jdbc.Driver \
--target-dir hdfs://bigdata01:9820/sqoopdata/sales_order2/dt=2022 \
--split-by orderId \
-m 1 \
--check-column orderId \
--incremental append \
--last-value 4 \
--fields-terminated-by '\t'

缺点是:每次还要记住上一次的last-value是几,记不住,怎么办?
sqoop 中的 job 可以完成自动增量导入。 具体查看 sqoop job中的用法。

五、导出 Export

第一个案例:将hdfs上的文件导出到mysql的表中

在hdfs上有一个文件,u2.txt
在home路径下创建文件,并创建数据:

1,18
2,20
3,30

上传到hdfs中:

hdfs dfs -put u2.txt /

在mysql中新建一个表,用于存放hdfs上的数据:

CREATE TABLE `u2` (
  `id` int(11) DEFAULT NULL,
  `age` int(11) DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

开始将hdfs上的文件导出到mysql中:

sqoop export --connect jdbc:mysql://bigdata01:3306/qfdb \
--username root \
--password 123456 \
--table u2 \
--export-dir '/u2.txt' \
--input-fields-terminated-by ',' \
-m 1

如果我们导出数据,有null值,需要特殊处理,否则报错,可以添加如下方式:


--null-string '\\N'  ## 遇到空字符串会填充\N字符
--null-non-string '0' # 遇到空数字会填充0

六、Sqoop中的job任务

1、好处

job的好处:
1、一次创建,后面不需要创建,可重复执行job即可
2、它可以帮我们记录增量导入数据的最后记录值(last_value)
3、job的元数据默认存储目录:$HOME/.sqoop/
4、job的元数据也可以存储于mysql中。

2、job的命令

usage: sqoop job [GENERIC-ARGS] [JOB-ARGS] [-- [<tool-name>] [TOOL-ARGS]]

Job management arguments:
   --create <job-id>            Create a new saved job
   --delete <job-id>            Delete a saved job
   --exec <job-id>              Run a saved job
   --help                       Print usage instructions
   --list                       List saved jobs
   --meta-connect <jdbc-uri>    Specify JDBC connect string for the
                                metastore
   --show <job-id>              Show the parameters for a saved job
   --verbose                    Print more information while working
sqoop job --list

创建一个job任务:

sqoop job --create  jjoobb -- import  --connect jdbc:mysql://bigdata01:3306/qfdb \
--username root \
--password 123456 \
--table u2 \
--delete-target-dir \
--target-dir '/sqoopdata/u3' \
-m 1

image.png
将java-json.jar 存放到 sqoop/lib 下
第一步: java-json.jar 存放到 sqoop/lib 下
第二步: sqoop-env.sh 中 添加 export HCAT_HOME=/usr/local/hive/hcatalog
第三步: 如果还有问题,删除 sqoop中的lib中 hive-exec-xxxx.jar 这个jar包。

job的相关操作:

sqoop job --list 
sqoop job --show jjoobb
sqoop job --delete jjoobb