基本环境描述:
centos6.8+sqoop1.4.6
此外sqoop需要依赖于hadoop。在这里需要用到hbase(需要依赖zookeeper)、hive与mysql关系数据库之间的数据导入/导出,在此基本的依赖环境都已搭建好。
一、sqoop安装配置
1 修改sqoop-env.sh(mv from sqoop-tmplate-env.sh),具体根据自己的环境以及需求来配置。
export HADOOP_COMMON_HOME=/usr/SFT/hadoop-2.7.2
export HADOOP_MAPRED_HOME=/usr/SFT/hadoop-2.7.2
export HIVE_HOME=/usr/SFT/hive-1.2.1
export ZOOKEEPER_HOME=/usr/SFT/zookeeper-3.4.12
export ZOOCFGDIR=/usr/SFT/zookeeper-3.4.12
export HBASE_HOME=/usr/SFT/hbase-1.3.1
2 将mysql-connector jar包拷贝到lib目录下
3 测试是否安装成功
bin/sqoop help
4 测试是否能够连接到mysql,能显示出目标数据库相关信息表明已经可以成功连接了
/usr/SFT/sqoop-1.4.6/bin/sqoop list-databases --connect jdbc:mysql://chdp11:3306/ --username root --password root
先来捋一捋相关概念(sqoop是Hadoop大数据体系阵营的,如此就容易辨析内外了)
导入(import)数据从关系型数据库(如mysql)导入到大数据存储架构(hive hbase) 导出(export)数据从大数据存储架构导到关系型数据库(如mysql)
二、基本操作
1、mysql数据准备
创建表,插入数据
create table stu(
id varchar(10) primary key auto_increment ,
name varchar(20),
age int(10)
);
顺便复习下mysql,用三种方式插入数据,个人认为比较严谨的方法是指定列插入。
insert into stu values(null,'wangwu' , 13);
insert into stu(id,name,age) values(null,'alex' , 16);
insert into stu(name,age) values('tom' , 14);
2 全表导入到hdfs(若指定目录不存在会自动创建)
#load all of data frome target table
bin/sqoop import \
--connect jdbc:mysql://chdp11:3306/test \
--username root \
--password root \
--table stu \
--target-dir /sqoop/data \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t"
可以看到启动了MR任务
3 部分表数据查询导入到hdfs(注意是简单查询)
#注意$在被双引号包裹时的字符转义问题
#query table to import , using(must) $CONDITIONS in where clause to remain data orderly
bin/sqoop import \
--connect jdbc:mysql://chdp11:3306/test \
--username root \
--password root \
--query 'select name,age from stu where age<=15 and $CONDITIONS;'
--target-dir /sqoop/data \
--delete-target-dir \
--num-mappers 1 \
4 指定列 、行过滤导入到hdfs(实际用的比较少)
bin/sqoop import \
--connect jdbc:mysql://chdp11:3306/test \
--username root \
--password root \
--table stu \
--columns name,age \
--where id="1" \
--target-dir /sqoop/data \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t"
5 导入到hive
bin/sqoop import \
--connect jdbc:mysql://chdp11:3306/test \
--username root \
--password root \
--table stu \
--num-mappers 1 \
--hive-import \
--fields-terminated-by "\t" \
--hive-overwrite \
--hive-table sq_stup
注:
1 数据导入时先将数据上传到hdfs的临时目录,而后移动到hive元数据对应的数据目录,
与一次导入相比效率相差并不会太大,因为第二次移动数据(mv)时只是修改namenode
元数据,而不会移动实际数据存放的位置。
2 在数据导入中若hive不存在指定表则会自动创建。
6 导入到hbase
#split by 指定多个rowkey拼接时的分隔符,如下rowkey会被组合成“id-age”的模式/usr/SFT/sqoop-1.4.6/bin/sqoop import \
--connect jdbc:mysql://chdp11:3306/test \
--username root \
--password root \
--table stu \
--columns "id,name,age" \
--column-family "info" \
--hbase-create-table \
--hbase-row-key "id","age" \
--hbase-table "sq_stup" \
--num-mappers 1 \
--split-by "_"
注:
和hive的表自动创建不同,sqoop1.4.6只支持HBase1.0.1之前的版本自动创建表
这里用的是hbase-1.3.1,所以在此之前先创建一下表吧
hive (default)>create 'sq_stup','info'
7 数据导出到mysql
HIVE/HDFS到RDBMS/usr/SFT/sqoop-1.4.6/bin/sqoop export \
--connect jdbc:mysql://chdp11:3306/test \
--username root \
--password root \
--table stu \
--columns "name,age" \
--num-mappers 1 \
--export-dir /sqoop/data \
--input-fields-terminated-by "\t"
注:
1、Mysql中如果表不存在,不会自动创建,故而要自行创建
2、在此导入数据过程中若出现错误有时不会在控制台打印,只能查看历史服务器了(记得启动yarn历史服务器)
3、注意导出原数据要和目标数据的列数据类型一一对应以及列数量需要相等,最好指定要导出的数据列
Sqoop导入导出Null存储一致性问题
4、Hive中的Null在底层是以“\N”来存储,而MySQL中的Null在底层就是Null,为了保证数据两端的一致性。在导出数据时采用–input-null-string和–input-null-non-string两个参数。导入数据时采用–null-string和–null-non-string。
5、Sqoop数据导出一致性问题
如Sqoop在导出到Mysql时,使用4个Map任务,过程中有2个任务失败,那此时MySQL中存储了另外两个Map任务导入的数据,此时老板正好看到了这个报表数据。而开发工程师发现任务失败后,会调试问题并最终将全部数据正确的导入MySQL,那后面老板再次看报表数据,发现本次看到的数据与之前的不一致,这在生产环境是不允许的。
官网:http://sqoop.apache.org/docs/1.4.6/SqoopUserGuide.html
Since Sqoop breaks down export process into multiple transactions, it is possible that a failed export job may result in partial data being committed to the database. This can further lead to subsequent jobs failing due to insert collisions in some cases, or lead to duplicated data in others. You can overcome this problem by specifying a staging table via the --staging-table option which acts as an auxiliary table that is used to stage exported data. The staged data is finally moved to the destination table in a single transaction.
–staging-table方式
sqoop export --connect jdbc:mysql://192.168.137.10:3306/user_behavior --username root --password root --table stu --columns username,password --fields-terminated-by “\t” --export-dir “/user/hive/warehouse/tmp.db/stu${day}” --staging-table stu --clear-staging-table --input-null-string ‘\N’
三、脚本打包
使用脚本可以方便定时任务的配置执行
1 创建一个.opt文件编写sqoop脚本
#sq_expToMysql.optexport
--connect jdbc:mysql://chdp11:3306/test
--username root
--password root
--table stu
--columns "name,age"
--num-mappers 1
--export-dir /sqoop/data
--input-fields-terminated-by "\t"
2 使用sqoop工具执行该脚本
/usr/SFT/sqoop-1.4.6/bin/sqoop --options-file sq_expToMysql.opt
四、错误整理
1、sqoop export导出数据时出错, Can’t export data, please check failed map task log…NoSuchElementException
2、 ERROR sqoop.Sqoop: Error while expanding arguments