一、概述
sqoop是hive、hdfs、hbase等与RDMBS(mysql等)之间的沟通桥梁,主要通过JDBC与RDMBS进行交互。有两个版本sqoop1和sqoop2,sqoop1架构简单,使用非常方便(由于我使用的是sqoop1,所以本文主要介绍sqoop1),sqoop2是c/s架构,需要一个tomcat部署server端,并且提供了更多的访问方式:REST API、WEBUI、CLI、JAVA API等,并且提供了更安全的访问方式(主要是密码不会是明文)。但是sqoop主要在内网是用所以这都无所谓了。
二、部署
1、安装前的准备
去官方下载最新的安装包,下载地址:https://github.com/apache/sqoop/releases
下载mysql的连接jar包,下载地址:http://central.maven.org/maven2/mysql/mysql-connector-java/8.0.9-rc/mysql-connector-java-8.0.9-rc.jar
请确保已经提前安装好hadoop、hive。
2、安装
#tar xf sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz -C /data/
#cd /data/sqoop-1.4.7.bin__hadoop-2.6.0/lib
#wget http://central.maven.org/maven2/mysql/mysql-connector-java/8.0.9-rc/mysql-connector-java-8.0.9-rc.jar
#cd /data/sqoop-1.4.7.bin/__hadoop-2.6.0/conf
添加系统环境变量
#vim /etc/profile
export SQOOP_HOME=/data/sqoop-1.4.7.bin__hadoop-2.6.0
export PATH=$SQOOP_HOME/bin:$PATH
export HADOOP_CLASSPATH=$CLASSPATH:$HIVE_HOME/lib/*
修改sqoop-env.sh
#cp sqoop-env-template.sh sqoop-env.sh
添加如下内容:
#vim sqoop-env.sh
export HADOOP_COMMON_HOME=/data/hadoop-2.7.5
export HADOOP_MAPRED_HOME=/data/hadoop-2.7.5
export HIVE_HOME=/data/apache-hive-2.3.2-bin
export HIVE_CONF_DIR=$HIVE_HOME/conf
#vim $JAVA_HOME/jre/lib/security/java.policy
在grant{}内部添加如下内容:
permission javax.management.MBeanTrustPermission "register";
3、替换lib目录下面想应的jar包,否则是用的时候会报错
1)报错:
main ERROR Could not register mbeans java.security.AccessControlException: access denied ("javax.management.MBeanTrustPermission" "register")
解决方法:
#vim $JAVA_HOME/jre/lib/security/java.policy
在grant{}内部添加如下内容:
permission javax.management.MBeanTrustPermission "register";
2)报错:
NoSuchMethodError: com.fasterxml.jackson.databind.ObjectMapper.readerFor
是由于sqoop的lib目录下面的jackson相关的包的版本与hive的lib目录下的jackson相关jar包的版本不一致导致的。
解决方法:
将hive下的所有jackson相关jar全部copy到sqoop的lib目录下面
#cp -r $HIVE_HOME/lib/jackson-* $SQOOP_HOME/lib/
然后将重复的低版本的全部删掉就可以了。(切记不要全部删除,有些是不重复的)
3)报错:
ERROR tool.ImportTool: Encountered IOException running import job: java.io.IOException: java.lang.ClassNotFoundException: org.apache.hadoop.hive.conf.HiveConf
解决方法:
#vim /etc/profile
export HADOOP_CLASSPATH=$CLASSPATH:$HIVE_HOME/lib/*
#source /etc/profile
4)报错:
ERROR sqoop.Sqoop: Got exception running Sqoop: java.lang.RuntimeException: java.lang.RuntimeException: java.sql.SQLException: The connection property 'zeroDateTimeBehavior' acceptable values are: 'CONVERT_TO_NULL', 'EXCEPTION' or 'ROUND'. The value 'convertToNull' is not acceptable.
java.lang.RuntimeException: java.lang.RuntimeException: java.sql.SQLException: The connection property 'zeroDateTimeBehavior' acceptable values are: 'CONVERT_TO_NULL', 'EXCEPTION' or 'ROUND'. The value 'convertToNull' is not acceptable
解决方法:
使用命令是又一个jdbc的url,在url的后面加上zeroDateTimeBehavior=CONVERT_TO_NULL。
#sqoop import --connect jdbc:mysql://10.0.2.248:3306/test?zeroDateTimeBehavior=CONVERT_TO_NULL --username root --password hive123 --table a --hive-import --fields-terminated-by ',' --hive-overwrite -m 1
三、使用
1)将mysql数据导入到hive
创建hive表:
# sqoop create-hive-table --connect jdbc:mysql://10.0.2.248:3306/test --username root --password hive123 --table a --hive-table tt --fields-terminated-by ',' --hive-overwrite --as-parquetfile --target-dir /data/
将数据导入到hive表:
#sqoop import --connect jdbc:mysql://10.0.2.248:3306/test?zeroDateTimeBehavior=CONVERT_TO_NULL --username root --password hive123 --table a --hive-import --fields-terminated-by ',' --hive-overwrite -m 1 --as-parquetfile
#sqoop import --connect jdbc:mysql://10.0.2.248:3306/test?zeroDateTimeBehavior=CONVERT_TO_NULL --username root --password hive123 --table userlog --fields-terminated-by "\t" --lines-terminated-by "\n" --hive-import --hive-overwrite --create-hive-table --hive-table userlog.userlog --delete-target-dir
将数据导入到hive指定的库中:
#sqoop import --connect jdbc:mysql://10.0.2.248:3306/test?zeroDateTimeBehavior=CONVERT_TO_NULL --username root --password hive123 --table porder0 --hive-import --hive-overwrite --hive-database bigdata -m 1
导入部分字段:
#sqoop import --connect jdbc:mysql://10.0.2.248:3306/test?zeroDateTimeBehavior=CONVERT_TO_NULL --username root --password hive123 --table b --columns id,csv_date --hive-import --fields-terminated-by ',' --hive-overwrite --direct -m 1 --delete-target-dir
2)将mysql数据增量导入到hive里面:
#sqoop import --connect jdbc:mysql://10.0.2.248:3306/test?zeroDateTimeBehavior=CONVERT_TO_NULL --username root --password hive123 --table a --hive-import --fields-terminated-by ',' --hive-overwrite -m 1 --as-parquetfile
#sqoop import --connect jdbc:mysql://10.0.2.248:3306/test?zeroDateTimeBehavior=CONVERT_TO_NULL --username root --password hive123 --table a -m 1 --target-dir /test/a_2 --incremental lastmodified --check-column crt_date --where crt_date>="2016-12-26 17:04:20" --as-parquetfile
3)codegen生成jar包:
#sqoop codegen --connect jdbc:mysql://10.0.2.248:3306/test?zeroDateTimeBehavior=CONVERT_TO_NULL --username root --password hive123 --table a
4)合并
#sqoop merge --new-data /test/a_2 --onto /test/a_1 --target-dir /test/a_merge --jar-file /tmp/sqoop-root/compile/57c71c4b6aa32458bb7a2d2636ba673f/a.jar --class-name a --merge-key id
注:–class-name a(这里是表名)
5)将合并后的数据导入到hive:
#cat hive.ql
drop table a;
create table if not exists a(id int, name string, csr_date timestamp) row delimited fields terminated by ',' stored as parquet;
load data inpath "/test/a_merge/" into table a;
#hive -f hive.ql
将hive里的数据导入到mysql:
1、根据hive里面表的结构,创建mysql表:
>create table if not exists test(id int, name varchar(40));
2、导入数据
#sqoop export --connect jdbc:mysql://10.0.2.248:3306/test?zeroDateTimeBehavior=CONVERT_TO_NULL --username root --password hive23 --table test --export-dir /user/hive/warehouse/a -m 1 --input-fields-terminated-by ','
将mysql数据导入到hdfs中
#sqoop import --connect jdbc:mysql://10.0.2.248:3306/sqoop?zeroDateTimeBehavior=CONVERT_TO_NULL --username root --password hive123 --table test -m 1 --as-parquetfile --target-dir /user/hive/result
参数详解:
--append 将数据追加到 hdfs 中已经存在的 dataset 中已经存在的 dataset 中。使用该参数, sqoop 将把数据先导入到一个临时目录中,然后重新给文件命 名到一个正式的目录中,以避免和该目录中已存在的文件重名。
--as-avrodatafile 将数据导入到一个 Avro 数据文件中
--as-sequencefile 将数据导入到一个 sequence 文件中
--as-parquetfile 将数据导入到一个parquet文件里面
--as-textfile 将数据导入到一个普通文本文件中,生成该文本文件后,可以在 hive 中通过 sql 语句查询出结果。
--boundary-query <statement> 边界查询,也就是在导入前先通过 SQL 查询得到一个结果集,然后导入的数据就是该结果集内的数据,格式如: --boundary-query 'select id,no from t where id = 3' ,表示导入的数据为 id=3 的记录,或者 select min(<split-by>), max(<split-by>) from <table name> ,注意查询的字段中不能有数据类型为字符串的字段,否则会报错
--columns<col,col> 指定要导入的字段值,格式如: --columns id,username
--direct 直接导入模式,使用的是关系数据库自带的导入导出工具。官网上是说这样导入会更快
--direct-split-size 在使用上面 direct 直接导入的基础上,对导入的流按字节数分块,特别是使用直连模式从 PostgreSQL 导入数据的时候,可以将一个到达设定大小的文件分为几个独立的文件。
--inline-lob-limit 设定大对象数据类型的最大值
-m,--num-mappers 启动 N 个 map 来并行导入数据,默认是 4 个,最好不要将数字设置为高于集群的节点数
--query , -e <sql> 从查询结果中导入数据,该参数使用时必须指定– target-dir 、– hive-table ,在查询语句中一定要有 where 条件且在 where 条件中需要包含 \$CONDITIONS ,示例: --query 'select * from t where \$CONDITIONS ' --target-dir /tmp/t – hive-table t
--split-by <column> 表的列名,用来切分工作单元,一般后面跟主键 ID
--target-dir <dir> 指定 hdfs 路径
--delete-target-dir 删除目标目录
--warehouse-dir <dir> 与 --target-dir 不能同时使用,指定数据导入的存放目录,适用于 hdfs 导入,不适合导入 hive 目录
--where 从关系数据库导入数据时的查询条件,示例: --where "id = 2"
-z,--compress 默认情况下数据是没被压缩的,通过该参数可以使用 gzip 压缩算法对数据进行压缩,适用于 SequenceFile, text 文本文件 , 和 Avro 文件
--compression-codec Hadoop 压缩编码,默认是 gzip
--table <table-name> 关系数据库表名,数据从该表中获取
--hive-import 导入到hive中
--hive-overwrite 覆盖原有的数据
--hive-database 指定导入到hive中指定的库