一、复习flume
1. flume的简介
- flume是apache基金会旗下的一款项目
- flume用于采集数据,通常采集的是行为数据(日志文件)
(结构上分类:结构化数据,半结构化的数据,非结构化的数据
采集数据的种类进行分类:行为数据(日志文件),业务数据,内容数据,第三方数据源)
- flume具有的特点:分布式的,可靠性的,高可用的等
2. flume的体系结构
- 运行单元是agent, agent至少包含一个source,一个channel,一个sink
- source: 用于与数据源交互,将数据封装成event,传输给channel
- channel:用于缓存event,提高传输效率,提高数据传输的安全性,并将数据传输给sink
常用的有memory: 内存 效率更高
file: 文件 更安全
- sink: 用于接收channel里的event, 将数据存储到文件系统上或者是下游的agent的source中
- event: 是采集的每一条记录,event的结构有两部分:
(1)Map<String,String>的header,存储键值对
(2)byte[]类型的body,存储的是采集的数据
- interceptor:拦截器,拦截event,分析event和修改event
作用位置:source和sink端
常用拦截器:timestamp,host,static,regex,自定义
- selector: 选择器,将event分发到不同的channel里
位置:source端
常用的选择器:
(1)replicating,复用选择器: 复制event到所有的channel里,
(2)multiplexing,多副路选择器:根据键值对的不同,将event分到不同的channel里
- processor:处理器, 可以自动容灾或者是负载均衡
failover
load_balance: random,round_robin
- flow: event在传输过程中的一个抽象概念
3. flume的数据流模型
- 单agent
- 多agent串联
- 多agent汇聚并联
- sinkgroups
4. flume的方案配置模板
5. flume的安装
6. flume的基本用法
常用的source: spooldir,taildir,exec,syslogtcp,http,avro
常用的channel: memory,file
常用的sink: logger,hdfs,avro, hbase,hive
7. flume的拦截器和选择器
8. flume的处理器(自动容灾和负载均衡)
二、sqoop的简介
2.1 产生背景
- 数据仓库的数据应该是集成的,也就是说不光只有行为数据,还要有业务数据,这样一起分析才更具有意义
- 基于上述需求,业务数据也应该导入到数据仓库。
- 但是以前将业务数据(在关系型数据库中)导入到hadoop中是非常困难的,所有市场需要一款可以方便导入和导出的工具
- 此时sqoop,datax,kettle等工具应运而生
2.2 sqoop是什么
1. sqoop是apache基金会旗下的一款工具
2. 功能是可以将数据在关系型数据库和hadoop生态体系之间进行传输。
3. 导入(import):指的数据从关系型数据库传输到hadoop生态体系
导出(export):指的数据从hadoop生态体系到关系型数据库
2.3 sqoop的原理
1. sqoop底层使用的是mapreduce的N个MapTask来完成数据的导入导出
2. 由于使用MapTask,虽然能并行执行,加快速度,但是处理的数据依然是离线数据(静态数据),所以是一种批处理的方式,难以实现实时数据的导入导出。
3. 参考文档里的图片
2.4 sqoop的特点
优点:可以跨平台进行数据传输
缺点:不够灵活
目前只支持:
mysql<---->hdfs
mysql<---->hive
mysql---->hbase
三、sqoop的安装
1、上传、解压、更名
[root@qianfeng01 ~]# tar -zxvf sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz -C /usr/local/
[root@qianfeng01 local]# mv sqoop-1.4.7.bin__hadoop-2.6.0/ sqoop
2、配置环境变量
[root@qianfeng01 local]# vim /etc/profile
................
#sqoop environment
export SQOOP_HOME=/usr/local/sqoop
export PATH=$SQOOP_HOME/bin:$PATH
[root@qianfeng01 local]# source /etc/profile
3、配置sqoop的环境脚本文件
[root@qianfeng01 conf]# cp sqoop-env-template.sh sqoop-env.sh
#Set path to where bin/hadoop is available
export HADOOP_COMMON_HOME=/usr/local/hadoop
#Set path to where hadoop-*-core.jar is available
export HADOOP_MAPRED_HOME=/usr/local/hadoop
#set the path to where bin/hbase is available
export HBASE_HOME=/usr/local/hbase
#Set the path to where bin/hive is available
export HIVE_HOME=/usr/local/hive
#Set the path for where zookeper config dir is
export ZOOCFGDIR=/usr/local/zookeeper/conf
4、导入mysql驱动到lib目录
mysql-connector-java-5.1.xxx.jar
四、常用指令介绍
1)常用指令的查看
sqoop help
usage: sqoop COMMAND [ARGS]
Available commands:
codegen Generate code to interact with database records
create-hive-table Import a table definition into Hive
eval Evaluate a SQL statement and display the results
export Export an HDFS directory to a database table
help List available commands
import Import a table from a database to HDFS
import-all-tables Import tables from a database to HDFS
import-mainframe Import datasets from a mainframe server to HDFS
job Work with saved jobs
list-databases List available databases on a server
list-tables List available tables in a database
merge Merge results of incremental imports
metastore Run a standalone Sqoop metastore
version Display version information
2)查看指定命令的帮助信息
sqoop help COMMAND
1)比如查看ist-databases的帮助信息
sqoop help ist-databases
usage: sqoop list-databases [GENERIC-ARGS] [TOOL-ARGS]
Common arguments:
--connect <jdbc-uri> Specify JDBC
connect
string
--connection-manager <class-name> Specify
connection
manager
class name
--connection-param-file <properties-file> Specify
connection
parameters
file
--driver <class-name> Manually
specify JDBC
driver class
to use
--hadoop-home <hdir> Override
$HADOOP_MAPR
ED_HOME_ARG
--hadoop-mapred-home <dir> Override
$HADOOP_MAPR
ED_HOME_ARG
--help Print usage
instructions
--metadata-transaction-isolation-level <isolationlevel> Defines the
transaction
isolation
level for
metadata
queries. For
more details
check
java.sql.Con
nection
javadoc or
the JDBC
specificaito
n
--oracle-escaping-disabled <boolean> Disable the
escaping
mechanism of
the
Oracle/OraOo
p connection
managers
-P Read
password
from console
--password <password> Set
authenticati
on password
--password-alias <password-alias> Credential
provider
password
alias
--password-file <password-file> Set
authenticati
on password
file path
--relaxed-isolation Use
read-uncommi
tted
isolation
for imports
--skip-dist-cache Skip copying
jars to
distributed
cache
--temporary-rootdir <rootdir> Defines the
temporary
root
directory
for the
import
--throw-on-error Rethrow a
RuntimeExcep
tion on
error
occurred
during the
job
--username <username> Set
authenticati
on username
--verbose Print more
information
while
working
3)去官网上查询
http://sqoop.apache.org/docs/1.4.7/SqoopUserGuide.html#_literal_sqoop_list_databases_literal
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HNFhsmxA-1615385990983)(ClassNotes.assets/image-20201028104049913.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cWzCoLBz-1615385990987)(ClassNotes.assets/image-20201028104132124.png)]
五、sqoop的基本用法
5.1 查询数据库和表
1)查看数据库
sqoop list-databases --connect jdbc:mysql://10.36.149.27:3306 --username root --password 123456
sqoop list-databases --connect jdbc:mysql://qianfeng03:3306 --username root --password @Mm123123
2)查看指定数据库hive下的表
sqoop list-tables \
--connect jdbc:mysql://qianfeng03:3306/hive \
--username root \
--password @Mm123123
5.2 mysql<==>hdfs
5.2.0 准备数据
create database sz2003 default character set utf8;
use sz2003;
## emp
表 有主键
DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (
`EMPNO` int(4) NOT NULL,
`ENAME` varchar(10),
`JOB` varchar(9),
`MGR` int(4),
`HIREDATE` date,
`SAL` int(7),
`COMM` int(7),
`DEPTNO` int(2),
PRIMARY KEY (`EMPNO`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `emp` VALUES ('7369', 'SMITH', 'CLERK', '7902', '1980-12-17', '800', null, '20');
INSERT INTO `emp` VALUES ('7499', 'ALLEN', 'SALESMAN', '7698', '1981-02-20', '1600', '300', '30');
INSERT INTO `emp` VALUES ('7521', 'WARD', 'SALESMAN', '7698', '1981-02-22', '1250', '500', '30');
INSERT INTO `emp` VALUES ('7566', 'JONES', 'MANAGER', '7839', '1981-04-02', '2975', null, '20');
INSERT INTO `emp` VALUES ('7654', 'MARTIN', 'SALESMAN', '7698', '1981-09-28', '1250', '1400', '30');
INSERT INTO `emp` VALUES ('7698', 'BLAKE', 'MANAGER', '7839', '1981-05-01', '2850', null, '30');
INSERT INTO `emp` VALUES ('7782', 'CLARK', 'MANAGER', '7839', '1981-06-09', '2450', null, '10');
INSERT INTO `emp` VALUES ('7788', 'SCOTT', 'ANALYST', '7566', '1987-04-19', '3000', null, '20');
INSERT INTO `emp` VALUES ('7839', 'KING', 'PRESIDENT', null, '1981-11-17', '5000', null, '10');
INSERT INTO `emp` VALUES ('7844', 'TURNER', 'SALESMAN','7698', '1981-09-08', '1500', '0', '30');
INSERT INTO `emp` VALUES ('7876', 'ADAMS', 'CLERK', '7788', '1987-05-23', '1100', null, '20');
INSERT INTO `emp` VALUES ('7900', 'JAMES', 'CLERK', '7698', '1981-12-03', '950', null, '30');
INSERT INTO `emp` VALUES ('7902', 'FORD', 'ANALYST', '7566', '1981-12-03', '3000', null, '20');
INSERT INTO `emp` VALUES ('7934', 'MILLER', 'CLERK', '7782', '1982-01-23', '1300', null, '10');
## 学生表 没有主键
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
`s_id` varchar(20) NOT NULL,
`s_name` varchar(20) NOT NULL DEFAULT '',
`s_birth` varchar(20) NOT NULL DEFAULT '',
`s_sex` varchar(10) NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `student` VALUES
('01','赵雷','1990-01-01','男'),
('02','钱电','1990-12-21','男'),
('03','孙风','1990-05-20','男'),
('04','李云','1990-08-06','男'),
('05','周梅','1991-12-01','女'),
('06','吴兰','1992-03-01','女'),
('07','郑竹','1989-07-01','女'),
('08','王菊','1990-01-20','女'),
('09','张飞','1990-9-25','男'),
('10','刘备','1990-01-25','男'),
('11','关羽','1990-01-25','男');
5.2.1 mysql—>hdfs
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FDjyWEI7-1615385990990)(ClassNotes.assets/image-20201028111041760.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BBBPVHcc-1615385990994)(ClassNotes.assets/image-20201028114137248.png)]
案例1)导入有主键表到hdfs
sqoop import \
--connect jdbc:mysql://qianfeng03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp \
--target-dir /sqoop/mysql-hdfs/emp
注意:数据的split 个数由maptask的数量控制,数据范围由切分字段最大值和最小值确定范围,然后均分
7934-7368 = 566 /4 141.25
7369~ 7368+141= 7509
7510 ~7509+141 = 7650
7651 ~7650+141 = 7791
7792~ 7791+141 = 7934
案例2)导入无主键表到hdfs
sqoop import \
--connect jdbc:mysql://qianfeng03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table student \
--target-dir /sqoop/mysql-hdfs/student
结论:无主键的表需要指定--split-by参数或者是将maptask的数量设置为1
修改如下:
第一种方式:
sqoop import \
--connect jdbc:mysql://qianfeng03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table student \
--target-dir /sqoop/mysql-hdfs/student \
--delete-target-dir \
-m 1
第二种方式:注意可能报错
sqoop import -Dorg.apache.sqoop.splitter.allow_text_splitter=true \
--connect jdbc:mysql://qianfeng03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table student \
--target-dir /sqoop/mysql-hdfs/student \
--split-by s_id
注意: 如果报以下错误,需要将提示中的属性和值添加到导入语句中
ERROR tool.ImportTool: Import failed: java.io.IOException: Generating splits for a textual index column allowed only in case of "-Dorg.apache.sqoop.splitter.allow_text_splitter=true" property passed as a parameter
案例3)指定列分隔符
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp \
--target-dir /sqoop/mysql-hdfs/emp \
--delete-target-dir \
--fields-terminated-by '\t' \
-m 1
案例4)测试columns
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--columns "empno,ename,deptno" \
--table emp \
--target-dir /sqoop/mysql-hdfs/emp \
--delete-target-dir \
--fields-terminated-by '\t' \
-m 1
案例5)测试where
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--columns "empno,ename,deptno" \
--table emp \
--where "deptno=10 or deptno=30" \
--target-dir /sqoop/mysql-hdfs/emp \
--delete-target-dir \
--fields-terminated-by '\t' \
-m 1
案例6)测试-e|–query
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--query 'select empno, ename,deptno from emp where $CONDITIONS and deptno=10' \
--target-dir /sqoop/mysql-hdfs/emp \
--delete-target-dir \
--fields-terminated-by '\t' \
--split-by 'empno'
注意事项:
--1. 如果使用--query 不能使用--table
--2. 如果使用--query, select语句中必须要有where子句,子句中必须要有$CONDITIONS
--3. select语句可以使用单引号,也可以使用双引号,如果使用双引号,那么$必须加转义字符
--4. 如果使用--query,需要指定切分字段,也就是参数--split-by
--5. 可以使用--where参数,但是不生效。
案例7)测试字符串类型的null处理和非字符串类型的null处理
mysql> update emp set job=null where empno = 7934;
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp \
--target-dir /sqoop/mysql-hdfs/emp \
--delete-target-dir \
--fields-terminated-by '\t' \
--null-string '\\N' \
--null-non-string '-1' \
-m 1
5.2.2 hdfs–>mysql
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wn0gbwp7-1615385990997)(ClassNotes.assets/image-20201028142336072.png)]
注意:导出时,mysql中的表必须提前创建。
1)创建一个带有主键约束的表emp_1,字段数与hdfs上的一致
DROP TABLE IF EXISTS `emp_1`;
CREATE TABLE `emp_1` (
`EMPNO` int(4) NOT NULL,
`ENAME` varchar(10),
`JOB` varchar(9),
`MGR` int(4),
`HIREDATE` date,
`SAL` int(7),
`COMM` int(7),
`DEPTNO` int(2),
PRIMARY KEY (`EMPNO`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2)创建一个带有主键约束的表emp_2,字段数少于hdfs上的列数
DROP TABLE IF EXISTS `emp_2`;
CREATE TABLE `emp_2` (
`EMPNO` int(4) NOT NULL,
`ENAME` varchar(10),
`JOB` varchar(9),
`MGR` int(4),
`HIREDATE` date,
`SAL` int(7),
PRIMARY KEY (`EMPNO`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3)创建一个带有主键约束的表emp_3,字段数多于hdfs上的列数
DROP TABLE IF EXISTS `emp_3`;
CREATE TABLE `emp_3` (
`EMPNO` int(4) NOT NULL,
`ENAME` varchar(10),
`JOB` varchar(9),
`MGR` int(4),
`HIREDATE` date,
`SAL` int(7),
`COMM` int(7),
`DEPTNO` int(2),
`age` int,
PRIMARY KEY (`EMPNO`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
4)创建一个无主键的表
DROP TABLE IF EXISTS `emp_4`;
CREATE TABLE `emp_4` (
`EMPNO` int(4) NOT NULL,
`ENAME` varchar(10),
`JOB` varchar(9),
`MGR` int(4),
`HIREDATE` date,
`SAL` int(7),
`COMM` int(7),
`DEPTNO` int(2)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
案例1)代有主键字段的表,字段数相同
sqoop export \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp_1 \
--export-dir /sqoop/mysql-hdfs/emp \
-m 1
注意事项:导出时,字段之间的切分符号默认是逗号。如果hdfs上的文件不是逗号分隔符,需要使用--fields-terminated-by或--input-fields-terminated-by参数指定分隔符,参考下面的例子
sqoop export \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp_1 \
--export-dir /sqoop/mysql-hdfs/emp \
--input-fields-terminated-by '\t' \
-m 1
案例2)代有主键字段的表,字段数少于hdfs上列数
sqoop export \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp_2 \
--export-dir /sqoop/mysql-hdfs/emp \
--input-fields-terminated-by '\t' \
-m 1
案例3)代有主键字段的表,字段数多于hdfs上列数
sqoop export \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp_3 \
--export-dir /sqoop/mysql-hdfs/emp \
--input-fields-terminated-by '\t' \
-m 1
案例4)导出到无主键约束的表中
sqoop export \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp_4 \
--export-dir /sqoop/mysql-hdfs/emp \
--input-fields-terminated-by '\t' \
-m 1
案例5)测试类型没有对应上
DROP TABLE IF EXISTS `emp_5`;
CREATE TABLE `emp_5` (
`EMPNO` int(4) NOT NULL,
`ENAME` varchar(10),
`JOB` varchar(9),
`MGR` int(4),
`SAL` int(7),
`COMM` int(7),
`DEPTNO` int(2)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
sqoop export \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp_5 \
--export-dir /sqoop/mysql-hdfs/emp \
--input-fields-terminated-by '\t' \
-m 1
结论:
1. 导出时,mysql中的表必须提前创建。
2. 导出时,字段之间的切分符号默认是逗号。如果hdfs上的文件不是逗号分隔符,需要使用--fields-terminated-by或--input-fields-terminated-by参数指定分隔符
3. 导出时,是按照hdfs上文件从左到右的顺序给mysql表的字段赋值
4. 导出时,mysql的表的字段数与hdfs上的列数可以不相同
5. 导出时,字段类型要一致
6. 带有主键约束的mysql表,要注意导出的数据的主键约束的情况,不能重复
7. 使用--columns给mysql中的某些字段赋值时,没有包含在参数中的字段要么有默认值,要么不能设置not null
8. 在sqoop1.4.7中,hdfs上的字符串'null'是可以转成mysql中字符串类型字段的null值,
也可以转成mysql中非字符串类型字段的null值。
案例6)使用参数–columns
DROP TABLE IF EXISTS `emp_6`;
CREATE TABLE `emp_6` (
empno int(4),
ename varchar(10),
job varchar(9),
mgr int(4),
hiredate VARCHAR(20),
sal int(7),
comm int(7),
deptno int(2)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
sqoop export \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--columns "ename,job,hiredate" \
--table emp_6 \
--export-dir /sqoop/mysql-hdfs/emp \
--input-fields-terminated-by '\t' \
-m 1
案例7)测试hdfs上的字符串’null’是可以转成mysql中字符串类型字段的null值,或者是非字符串类型的null值
sqoop export \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp_6 \
--export-dir /sqoop/mysql-hdfs/emp \
--input-fields-terminated-by '\t' \
-m 1
案例8)input-null-string和input-null-non-string参数的用法
上述参数的功能:将hdfs上的值在mysql中设置为null。
sqoop export \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp_6 \
--export-dir /sqoop/mysql-hdfs/emp \
--input-fields-terminated-by '\t' \
--input-null-string '\\N' \
--input-null-non-string '-1' \
-m 1
sqoop export \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp_6 \
--export-dir /sqoop/mysql-hdfs/emp \
--input-fields-terminated-by '\t' \
--input-null-string 'KING' \
--input-null-non-string '10' \
-m 1
5.3 mysql<==>hive
5.3.1 mysql–>hive
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0cnYqlUM-1615385990999)(ClassNotes.assets/image-20201028154521677.png)]
案例1)导入hive中
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp \
--hive-import \
--hive-table 'emp1'
注意:如果报以下错误,说明sqoop的lib下缺少hive的common包
Import failed: java.io.IOException: java.lang.ClassNotFoundException: org.apache.hadoop.hive.conf.HiveConf
案例2)测试–hive-overwrite
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp \
--hive-import \
--hive-overwrite \
--hive-table 'emp1' \
-m 1
结论:
1. 添加--hive-overwrite会覆盖原有的hive的表数据,反之没有此参数,表示追加数据。
2. 必须要有--hive-import选项。
3. 从mysql中导入到hive中时,如果不指定分隔符,默认使用的是^A,可以使用fields-terminated-by指定分隔符
案例3):指定分隔符
sqoop import \
--connect jdbc:mysql://mei01:3306/sz2003 \
--username root \
--password 123456 \
--table emp \
--hive-overwrite \
--hive-table 'emp11' \
--fields-terminated-by '\001' \
-m 1
案例4)使用分区字段参数导入到hive中
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password 123456 \
--table emp \
--hive-import \
--hive-overwrite \
--hive-table 'emp2' \
--fields-terminated-by ',' \
--hive-partition-key 'dt' \
--hive-partition-value "2020-10-28" \
-m 1
5.3.2 hive–>mysql
hive到mysql的本质其实就是hdfs到mysql
-- 先在mysql中创建表结构
DROP TABLE IF EXISTS `emp_7`;
CREATE TABLE `emp_7` (
empno int(4),
ename varchar(10),
job varchar(9),
mgr int(4),
hiredate VARCHAR(20),
sal int(7),
comm int(7),
deptno int(2)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 将hive表emp2对应的目录下的数据导出到mysql的表中
sqoop export \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp_7 \
--export-dir /user/hive/warehouse/emp2/dt=2020-10-28 \
--fields-terminated-by ',' \
-m 1
sqoop import \
--connect jdbc:mysql://localhost:3306/my2003 \
--username mei \
--password 123456 \
--table user \
--hive-import \
--hive-overwrite \
--hive-table 't1.emp' \
--fields-terminated-by '\t' \
--hive-partition-key 'dt' \
--hive-partition-value '2020-12-12' \
-m 1
sqoop export \
--connect jdbc:mysql://localhost:3306/my2003 \
--username mei \
--password 123456 \
--table user \
--export-dir /user/emp/dt=2020-12-12 \
--fields-terminated-by '\t' \
-m 1
5.4 mysql==>hbase
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BltKdrij-1615385991000)(ClassNotes.assets/image-20201028164454118.png)]
案例1)
sqoop import \
--connect jdbc:mysql://mei01:3306/sz2003 \
--username root \
--password 123456 \
--table emp \
--column-family 'f1' \
--hbase-create-table \
--hbase-table 'myemp' \
--hbase-row-key 'EMPNO' \
-m 1
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--query 'select ename,job from emp where $CONDITIONS and deptno=10' \
--column-family 'f1' \
--hbase-create-table \
--hbase-table 'myemp' \
--hbase-row-key 'empno' \
-m 1
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table 'emp' \
--column-family 'f1' \
--hbase-create-table \
--hbase-table 'myemp' \
-m 1
结论:
注意:在导入到hbase中时:
--1. rowkey大小写问题
如果是--table [--where] 那么hbase-row-key的字段名必须大写
如果是--query并且指定了主键字段, hbase-row-key的字段名必须和query中的大小写一致,否则也要是大写的
--2. rowkey的指定问题
--hbase-row-key,参数可以忽略,忽略情况下,主动将mysql中的主键作为rowkey,不指定时,必须使用--table,也可以指定出来
-- 如果mysql中的主键是复合键,那么此属性必须指定,并且使用逗号分隔
-- 如果mysql中没有主键约束,那么应该指定--hbase-row-key
六 sqoop的高阶用法
6.1 增量导入
6.1.1 应用场景
在实际生产环境中,业务数据在导入到数仓里时,通常使用增量导入的方式。这样可以避免有些数据重复导入的操作。
1. 经常需要导入的RDBMS表,建议使用增量导入
2. RDBMS表数据量特别大,但是变化小,建议使用增量导入
6.1.2 增量导入的方式
1. 可以使用--query参数,在select语句中进行条件限制来导入数据,缺点是条件需要人为的设置
2. 可以使用--incremental,进行增量导入,通常这个参数要配合--check-column和--last-value一起使用
6.1.3 案例演示
1)演示query的增量导入
昨天导入的数据如下:
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--driver 'com.mysql.jdbc.Driver' \
--username root \
--password @Mm123123 \
--query 'select * from emp where deptno in(10,20) and $CONDITIONS' \
--target-dir /tmp111 \
--hive-import \
--hive-table 'sz2003.emp101' \
--fields-terminated-by '\t' \
--null-string '\\N' \
--null-non-string '0' \
-m 1
注意事项: 向hive中导入数据时,使用--table时,会临时存储到/user/root/mysql-tableName目录下,然后再load到hive的表中
如果使用的是--query,必须使用--target-dir指定临时目录
今天导入新增加的30号部门的数据
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--driver 'com.mysql.jdbc.Driver' \
--username root \
--password @Mm123123 \
--query 'select * from emp where deptno =30 and $CONDITIONS' \
--target-dir /tmp111 \
--hive-import \
--hive-table 'sz2003.emp101' \
--fields-terminated-by '\t' \
--null-string '\\N' \
--null-non-string '0' \
-m 1
2)测试–append参数
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--driver 'com.mysql.jdbc.Driver' \
--username root \
--password @Mm123123 \
--append \
--query 'select * from emp where deptno =30 and $CONDITIONS' \
--target-dir /sqoop/hdfs-emp/ \
--fields-terminated-by '\t' \
--null-string '\\N' \
--null-non-string '0' \
-m 1
注意:可以使用--append参数向hdfs上追加数据,如果不指定此参数,会报目录已经存在。
3)测试incremental
1)提前准备一些数据
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--driver 'com.mysql.jdbc.Driver' \
--username root \
--password @Mm123123 \
--query 'select * from emp where empno<7400 and $CONDITIONS' \
--target-dir /sqoop/hdfs-emp/ \
--delete-target-dir \
--fields-terminated-by '\t' \
--null-string '\\N' \
--null-non-string '0' \
-m 1
2) 增量导入
sqoop import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--driver 'com.mysql.jdbc.Driver' \
--username root \
--password @Mm123123 \
--incremental append \
--check-column 'empno' \
--last-value '7800' \
--query 'select * from emp where $CONDITIONS' \
--target-dir /sqoop/hdfs-emp/ \
--fields-terminated-by '\t' \
--null-string '\\N' \
--null-non-string '0' \
-m 1
注意:增量导入时,不要由--delete-target-dir参数
--last-value: 从指定的值开始检查,如果有大于此值的数据,就认为是新数据,才会增量导入。导入后,会记录这次导入的最大值,为下一次增量导入做提示。
--check-column: 检查指定列,是否有新值,那么从意义上来说,指定的列应该具有唯一,非空,自增的特点。
注意:如果last-value的值由人来维护,那么很可能出现重复数据,人指定的值可能会出错,所以应该使用一种机制来自动维护last-value的值。
6.2 job的应用
6.2.1 job应用的优点
1. 可以将导入导出语句创建到job里,然后可以重复的执行job。避免重写一堆参数,也可以使用定时器来定时执行job
2. 如果job里封装了增量导入语句,因为job里自动维护了一堆参数,包括--last-value,因此执行job后,job会记录last-value的最新的值,以便下次导入新的行数据。
6.2.2 job的指令
[root@qianfeng01 ~]# sqoop job --help
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
6.2.3 案例演示1
1)创建一个job,相当于将导入语句封装到job里。想要执行导入功能,必须执行job
sqoop job --create job1 \
-- import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp \
--target-dir "/0911/job" \
--delete-target-dir \
-m 1
注意:创建job时,一定要添加import参数,要与前面的--之间有一个空格
如果报以下
ERROR sqoop.Sqoop: Got exception running Sqoop: java.lang.NullPointerException
java.lang.NullPointerException
at org.json.JSONObject.<init>(JSONObject.java:144)
需要将java-json.jar包导入到sqoop的lib目录下
2)查询所有的job
[root@qianfeng01 ~]# sqoop job --list
3)执行job
[root@qianfeng01 ~]# sqoop job --exec job1
4)写一个定时脚本执行,规定中午12点整和半夜12整执行
[root@qianfeng01 ~]# crontab -e
0 12,0 * * * /usr/local/sqoop/bin/sqoop job --exec job1
6.2.4 案例演示2
1)创建一个带有增量导入的job
sqoop job --create job2 \
-- import \
--connect jdbc:mysql://mei03:3306/sz2003 \
--username root \
--password @Mm123123 \
--table emp \
--incremental append \
--check-column 'empno' \
--last-value '0' \
--target-dir "/incremental/job" \
--fields-terminated-by ',' \
-m 1
- 查看指定job
[root@qianfeng01 ~]# sqoop job --show job2
可以看到job的元数据,包括各种参数,如last-value的值
3)执行job
[root@qianfeng01 ~]# sqoop job --exec job2
执行完后,会看到last-value变成了7934.
4)在mysql的emp表中插入以下三条记录
insert into emp (empno,ename,job,deptno) values (7933,'zhangsan','clerk',10);
insert into emp (empno,ename,job,deptno) values (7935,'lisi','clerk',10);
insert into emp (empno,ename,job,deptno) values (7936,'wangwu','clerk',10);
5)再次执行job2
[root@qianfeng01 ~]# sqoop job --exec job2
执行后,会看到之导入了大于7934的两条记录。last-value变成了7936
6.3 metastore的应用
6.3.1 metastore的介绍
1. metastore服务是sqoop的元数据服务,用于存储sqoop的job相关信息
2. 默认会使用内嵌的元数据库,存储位置位于~/.sqoop/下
3. 由于安全性问题,将job信息保存于关系型数据库中是最合适的,关系型数据库可以选择mysql
6.3.2 配置metastore服务项
步骤1)修改用户自定义配置文件
[root@qianfeng01 conf]# vim sqoop-site.xml
<configuration>
<property>
<name>sqoop.metastore.client.enable.autoconnect</name>
<value>true</value>
</property>
<property>
<name>sqoop.metastore.client.autoconnect.url</name>
<value>jdbc:mysql://mei03:3306/sqoop</value>
</property>
<property>
<name>sqoop.metastore.client.autoconnect.username</name>
<value>root</value>
</property>
<property>
<name>sqoop.metastore.client.autoconnect.password</name>
<value>@Mm123123</value>
</property>
<property>
<name>sqoop.metastore.client.record.password</name>
<value>true</value>
</property>
<property>
<name>sqoop.metastore.server.location</name>
<value>/usr/local/sqoop/sqoop-metastore/shared.db</value>
</property>
<property>
<name>sqoop.metastore.server.port</name>
<value>16000</value>
</property>
</configuration>
步骤2)在mysql中创建sqoop数据库
mysql> create database sqoop
步骤3)启动sqoop的服务项
[root@qianfeng01 ~]# sqoop metastore
或者后台启动
[root@qianfeng01 ~]# sqoop metastore &
步骤4)在sqoop库中要维护一张表SQOOP_ROOT
##方式1:可以使用sqoop的某一个语句进行连接,这样就可以创建此表
执行如下语句即可
sqoop job --list --meta-connect 'jdbc:mysql://mei03:3306/sqoop?user=root&password=@Mm123123'
执行后,SQOOP_ROOT表创建成功
##方式2)手动维护此表
CREATE TABLE `SQOOP_ROOT` (
`version` int(11) DEFAULT NULL,
`propname` varchar(128) NOT NULL,
`propval` varchar(256) DEFAULT NULL,
UNIQUE KEY `SQOOP_ROOT_unq` (`version`,`propname`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
步骤5)需要向SQOOP_ROOT中添加一条记录
insert into SQOOP_ROOT values (NULL, 'sqoop.hsqldb.job.storage.version', '0');
步骤6)修改两张表的存储引擎为myisam(innoDB引擎会引起事务锁超时情况)
alter table SQOOP_ROOT engine=myisam;
alter table SQOOP_SESSIONS engine=myisam;
6.3.3 案例演示1
1)创建一个job
sqoop job --create job1 \
--meta-connect 'jdbc:mysql://mei01:3306/sqoop?user=root&password=123456' \
-- import \
--connect "jdbc:mysql://mei01:3306/sz2003" \
--username root \
--password @Mm123123 \
--table emp \
--target-dir /1029/emp \
--append \
--fields-terminated-by ',' \
-m 1
2)查询metastore里保存的job
sqoop job --list \
--meta-connect 'jdbc:mysql://mei03:3306/sqoop?user=root&password=@Mm123123'
注意:由于sqoop-site.xml里的自动连接属性为true,所以可以不添加--meta-connect参数
3)执行metastore里保存的job
sqoop job --exec job3
6.3.4 案例演示2
1)创建增量导入的job
sqoop job --create job2 \
--meta-connect 'jdbc:mysql://mei01:3306/sqoop?user=root&password=123456' \
-- import \
--connect "jdbc:mysql://mei01:3306/sz2003" \
--username root \
--password @Mm123123 \
--table emp \
--incremental append \
--check-column empno \
--target-dir /1029/incremental/ \
--fields-terminated-by ',' \
-m 1
注意:第一次创建增量job时,last-value参数可以不指定,默认导入全表的数据,然后会自动维护last-value的值
2)执行
sqoop job --exec job4
注意:想要使用metastore保存增量导入的job,那么SQOOP_SESSIONS的存储引擎必须是myisam。否则在执行job,想要保存last-value时,会失败
3)在mysql的emp表中插入两条新数据
insert into emp (empno,ename,job,deptno) values (7937,'lisi','clerk',10);
insert into emp (empno,ename,job,deptno) values (7938,'wangwu','clerk',10);
4)再次执行job4
sqoop job --exec job4
6.4 sqoop的优化
-1. mapTask的数量不能超过yarn的Vcore的数目,默认情况下yarn的VCORE的数量是8
-2. 如果数据量比较小,在200M以内,建议使用一个MapTask
-3. split-by指定的字段最好是均分分布的数字类型或者是时间类型。
-4. --fetch-size的数目的数据总大小最好在128M以内。