一、聊概念
Sqoop就是将数据从MySQL导入到hdfs,hive,hbase中,从hdfs,hive中导出到mysql 的工具,底层使用的技术是MapReduce中的map。
MySQL有啥优势:执行效率很高,数据也很安全(支持事务)。
HDFS:存储海量数据(文件)
Hive:可以分析海量数据(N+1)
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的驱动包
不是安装包
将我们的驱动包,存放到 sqoop的lib目录下一份
第七步:验证是否成功 sqoop version
没有配置这个,留下了一个问题,随后再说:
三、sqoop的操作
1、常见的命令 sqoop help
2、直接执行命令
sqoop list-databases --connect jdbc:mysql://localhost:3306 --username root --password 123456
如果存在以下错误:
这种类型的错误,一看就是缺包。
缺少的是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中先有数据:
新建数据库
导入一些数据:
此处省略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个?
这个是默认的配置,会将我们mysql中的数据按照主键,进行切分,切分为4份。
它不是按照数据的条数/4 进行平均分配的。
2、为什么不是平均分配?
它是先求出主键的最大值,主键的最小值,最大值-最小值/4 = 跨度。
7934-7369=565 565 / 4 = 141 左右
3、为什么是 part-m-00000 ?
我们的sqoop 本质是mapreduce中的map任务,map任务的输出就是 part-m-xxxxx
4、为什么报错?
报错的原因是超时了,连接超时了。
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
如果通过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
给出了两个方案,要么告诉我按照哪个字段切割,要么指定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
如果看到这个异常,说明任务执行失败了,但是也会执行成功一部分,所以我们还是可以看到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
出现了一个错误,这个错误就是缺包。
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/
增量导入(重要的):
增量导入的意思是,今天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
将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