1 什么是Sqoop
Sqoop是一个在结构化数据和Hadoop之间进行批量数据迁移的工具,结构化数据可以是Mysql、Oracle等RDBMS。Sqoop底层用MapReduce程序实现抽取、转换、加载,MapReduce天生的特性保证了并行化和高容错率,而且相比Kettle等传统ETL工具,任务跑在Hadoop集群上,减少了ETL服务器资源的使用情况。在特定场景下,抽取过程会有很大的性能提升。
如果要用Sqoop,必须正确安装并配置Hadoop,因依赖于本地的hadoop环境启动MR程序;mysql、oracle等数据库的JDBC驱动也要放到Sqoop的lib目录下。本文针对的是Sqoop1,不涉及到Sqoop2,两者有大区别。
2 Sqoop安装配置
本人测试环境用的Hadoop版本为CDH5.7.0,所以Sqoop也下载该版本(本人操作用户均为hadoop)
wget
http://archive-primary.cloudera.com/cdh5/cdh/5/sqoop-1.4.6-cdh5.7.0.tar.gz
下载完毕后,解压tar包,这里-C是指定解压目录
tar -zxvf sqoop-1.4.6-cdh5.7.0.tar.gz -C ~/app
解压完成后,首先配置环境变量,我这里配置的个人环境变量,cd到hadoop用户的家目录
vi .bash_profile
添加环境变量
export SQOOP_HOME=/home/hadoop/app/sqoop-1.4.6-cdh5.7.0
export PATH=$SQOOP_HOME/bin:$PATH
然后进入sqoop下面的conf目录下,配置sqoop-env.sh,这里主要配置三个参数
export HADOOP_COMMON_HOME=/home/hadoop/app/hadoop-2.6.0-cdh5.7.0
export HADOOP_MAPRED_HOME=/home/hadoop/app/hadoop-2.6.0-cdh5.7.0
export HIVE_HOME=/home/hadoop/app/hive-1.1.0-cdh5.7.0
3 Sqoop测试
本人测试的是mysql到hdfs之间的导入导出,所以需要先把mysql的jdbc驱动放到sqoop的lib文件夹下。
要查看sqoop有哪些功能,可以
sqoop help
查看
这里会列出sqoop可跟的参数,下面我们来测试一些功能。
a 、list-databases
这个功能可以列出连接的关系型数据库下面所有的database。
我们先查下mysql下面所有的database。
我们再使用sqoop来查看
sqoop list-databases \
--connect jdbc:mysql://localhost:3306 \
--username root \
--password 123456
这里后面跟connect,username,和password,就可以读取mysql库的信息。
可以看到,查出来是没有问题的。
b、 list-tables
这个功能是列出mysql指定库下的所有表
sqoop list-tables \
--connect jdbc:mysql://localhost:3306/test \
--username root \
--password 123456
我在mysql的test库下建了一张lover表,测试一下
c 、import mysql–>hdfs
这个功能是从关系型数据库里往HDFS里面导入表,这里我测试上面的lover表
sqoop import \
--connect jdbc:mysql://localhost:3306/test \
--username root \
--password 123456 \
--delete-target-dir \
--table lover \
--fields-terminated-by '\t'
报错了,这里是缺少java-json.jar包。我们把java-json.jar放到sqoop的lib下,重新执行。执行成功,我们查看一下hdfs上的数据。
表lover的数据已经被我们导入到HDFS上了。
上面的参数我们还可以设置
mapreduce的job名字
--mapreduce-job-name xxx
如果目标文件存在则删除
--delete-target-dir
设置目标文件夹
--target-dir
设置字段之间的分隔符
--fields-terminated-by
指定字段
--columns
指定条件
--where
测试一下只抽取name age两个字段的数据,而且age>20,字段之间的分隔符为\t。
sqoop import \
--connect jdbc:mysql://localhost:3306/test \
--username root \
--password 123456 \
--table lover \
--target-dir lover_columns \
--mapreduce-job-name lover \
--columns 'name,age' \
--fields-terminated-by '\t' \
--where 'age>20'
执行完后,我们看下HDFS上的数据
而且我们在import的时候,可以传入sql语句进行导数。参数为
-e
下面来测试一下
sqoop import \
--connect jdbc:mysql://localhost:3306/test \
--username root \
--password 123456 \
--target-dir lover_sql \
--mapreduce-job-name lover_sql \
--fields-terminated-by '\t' \
--e "select * from lover where age>20 and \$CONDITIONS" \
--m 1
这里- -m 1的意思是不切分数据,HDFS里只有一份文件。执行完后查询下HDFS里面的数据。
可以看到,HDFS里面只有一份part。而且导出的数据也是正确的。
d、export hdfs–>mysql
sqoop也可以从hdfs导数据到mysql里。首先我们在mysql里面把表建好。把之前导入到HDFS里面的数据再导回mysql。我们建一张和lover表结构一样的表loverfromhdfs。
然后执行export语句
sqoop export \
--connect jdbc:mysql://localhost:3306/test \
--username root \
--password 123456 \
--table loverfromhdfs \
--export-dir /user/hadoop/lover \
--fields-terminated-by '\t'
执行完后,查询表loverfromhdfs
导入成功。
e、Mysql --> Hive
测试一下从mysql抽取到hive中,我们先在hive里建好表,不然自动创建表字段类型可能不对。
然后执行导入脚本
sqoop import \
--connect jdbc:mysql://localhost:3306/test \
--username root \
--password 123456 \
--table lover \
--delete-target-dir \
--hive-import \
--hive-table lover \
--fields-terminated-by '\t' \
--hive-overwrite \
--hive-database test
执行完后查询hive里面的数据
f hive --> mysql
我们再来测试下hive到mysql,再在mysql里面建一张表,loverfromhive。
然后执行语句
sqoop export \
--connect jdbc:mysql://localhost:3306/test \
--username root \
--password 123456 \
--table loverfromhive \
--export-dir /user/hive/warehouse/test.db/lover/part* \
--fields-terminated-by '\t'
–export-dir 指定hive表存储路径
执行完后,查看loverfromhive数据