Sqoop 安装使用及问题解决

Posted by Jackson on 2017-09-10

Sqoop 概述(SQL to Hadoop)

作用:将数据从RDBMS 和Hadoop 之间进行导入导出,底层采用的是MapReduce实现

两大版本:

  • 1.4.* Sqoop1
  • 1.99.* Sqoop2
1
2
3
4
5
6
基于Hadoop作为参考点/基准点		
导入: import
RDBMS ==> Hadoop

导出: export
Hadoop ==> RDBMS

Sqoop 的安装

下载 cdh5
wget http://archive.cloudera.com/cdh5/cdh/5/sqoop-1.4.6-cdh5.16.2.tar.gz

解压
tar -zxvf sqoop-1.4.6-cdh5.16.2.tar.gz -C ~/app/

配置系统环境变量
export SQOOP_HOME=/home/hadoop/app/sqoop-1.4.6-cdh5.16.2
export PATH=$SQOOP_HOME/bin:$PATH
source

配置文件:
$SQOOP_HOME/conf/
cp sqoop-env-template.sh sqoop-env.sh
export HADOOP_COMMON_HOME=/home/hadoop/app/hadoop-2.6.0-cdh5.16.2
export HADOOP_MAPRED_HOME=/home/hadoop/app/hadoop-2.6.0-cdh5.16.2
export HIVE_HOME=/home/hadoop/app/hive-1.1.0-cdh5.16.2

驱动包
cp mysql-connector-java-5.1.27-bin.jar $SQOOP_HOME/lib/

测试是否可用:

列出所有数据库
sqoop list-databases
–connect jdbc:mysql://bigdata01:3306
–password 123456
–username root

列出所有表
sqoop list-tables
–connect jdbc:mysql://bigdata01:3306/sqoop
–password 123456
–username root

RDBMS TO HDFS(Import)

全表导入

1
2
3
4
5
6
7
8
sqoop import \
--connect jdbc:mysql://bigdata01:3306/sqoop \
--password ruozedata --username root \
--table emp \
--target-dir /user/company \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t"

参数:

  • –table :指定被导入的表名
  • –target-dir:指定导入路径
  • –delete-target-dir:如果目标目录存在就删除它
  • –fields-terminated-by:指定字段分隔符
  • –columns :指定需要导入的列
  • -m:mapTask的个数
  • –fields-terminated-by :指定字段之间的分隔符

导入指定列

1
2
3
4
5
6
7
8
9
sqoop import \
--connect jdbc:mysql://bigdata01:3306/sqoop \
--password ruozedata --username root \
--table emp \
--columns "id,name" \
--target-dir /user/company \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t"

参数:

  • –columns :指定要导入的列多个列之间用逗号分隔

查询导入

1
2
3
4
5
6
7
8
9
sqoop import \
--connect jdbc:mysql://bigdata01:3306/sqoop \
--password ruozedata --username root \
--table emp \
--target-dir /user/company \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t" \
--query 'select id,name from student where id <=1 and $CONDITIONS;'

参数:

  • –query :指定查询SQL where条件要有$CONDITIONS
    注意: must contain ‘$CONDITIONS’ in WHERE clause.

如果query后使用的是双引号,则$CONDITIONS前必须加转义符,防止shell识别为自己的变量。

筛选导入

1
2
3
4
5
6
7
8
9
sqoop import \
--connect jdbc:mysql://bigdata01:3306/sqoop \
--password ruozedata --username root \
--table emp \
--target-dir /user/company \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t"
--where "id > 400"

增量导入数据

1
2
3
4
5
6
7
8
9
10
11
12
sqoop import \
--connect jdbc:mysql://bigdata01:3306/sqoop \
--password ruozedata --username root \
--table emp \
--target-dir /user/company \
--null-string "" \
--null-non-string "0" \
--check-column "id" \
--incremental append \
--fields-terminated-by '\t' \
--last-value 0
-m 1

参数:

  • –null-string:字符串为null怎么处理
  • –null-non-string:其他类型为null怎么处理
  • –check-column:根据哪一行做增量导入
  • –last-value:开始增量导入的上个位置

RDBMS To Hive(Import)

1
2
3
4
5
6
7
8
9
10
11
12
13
sqoop import \
--connect jdbc:mysql://bigdata01:3306/sqoop \
--password ruozedata --username root \
--table emp \
--hive-overwrite \
--delete-target-dir \
--null-string "" \
--null-non-string "0" \
--hive-import \
--hive-database default \
--hive-table staff \
--fields-terminated-by '\t' \
--num-mappers 1

参数:

  • –hive-import:数据从关系数据库中导入到hive表中
  • –hive-overwrite:覆盖掉在hive表中已经存在的数据
  • –hive-table:后面接hive表,默认使用MySQL的表名 如果导入的是分区表,需要指定分区的key和value
  • –hive-partition-key key \
  • –hive-partition-value value \

HDFS To RDBMS(Export)

先保证MySQL创建了一张和Hive一样表结构的表用来接收数据
注意表结构和分隔符都要一样

1
2
3
4
5
6
7
8
9
10
11
12
sqoop import \
-Dsqoop.export.records.per.statement=10 \
--connect jdbc:mysql://bigdata01:3306/sqoop \
--password ruozedata --username root \
--table emp \
--table staff \
--export-dir /user/company/ \
--null-string "" \
--null-non-string "0" \
--columns "id,name" \
--fields-terminated-by '\t' \
-m 1

参数:

  • –Dsqoop.export.records.per.statement:批量更新,每隔10条提交一次
  • –export-dir:导出的hdfs目录
  • –table:导入的表名
  • –columns:指定导入的列

注意:MySQL中表不存在会自动创建

Hive To RDBMS(Export)

1
2
3
4
5
6
7
sqoop import \
--connect jdbc:mysql://bigdata01:3306/sqoop \
--password ruozedata --username root \
--table emp \
--num-mappers 1 \
--export-dir /user/hive/warehouse/staff \
--input-fields-terminated-by "\t"

参数:

  • –export-dir:指定被导出的目录
  • –input-fields-terminated-by:导入的分隔符格式,和导入的fields-terminated-by有区别

Sqoop 导入导出一体化流程

Hive中创建表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CREATE TABLE emp_etl(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';

CREATE TABLE dept_etl(
deptno int,
dname string,
loc string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';

使用Sqoop将MySQL中的数据导入到Hive中

1
2
3
4
5
6
7
8
9
10
11
sqoop import \
--connect jdbc:mysql://bigdata01:3306/sqoop \
--password ruozedata \
--username root \
--table dept \
--hive-overwrite \
--delete-target-dir \
--hive-import --hive-database ruozedata_hive \
--hive-table dept_etl \
--fields-terminated-by '\t' \
-m 1

Hive中创建结果表

1
2
3
4
5
6
7
CREATE TABLE result_etl(
empno int,
ename string,
deptno int,
dname string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';

模拟分析过程

1
2
insert overwrite table result_etl select e.empno, e.ename, e.deptno, d.dname from 
emp_etl e join dept_etl d on e.deptno=d.deptno;

MySQL中创建结果表 etl_result

1
2
3
4
5
6
create table etl_result(
empno int,
ename varchar(10),
deptno int,
dname varchar(20)
);

将结果表导出到MySQL

1
2
3
4
5
6
7
8
sqoop export \
--connect jdbc:mysql://bigdata01:3306/sqoop \
--password ruozedata \
--username root \
--table etl_result \
--export-dir /user/hive/warehouse/ruozedata_hive.db/result_etl \
--fields-terminated-by '\t' \
-m 1

Shell 中操作数据库

1
2
3
4
mysql -uroot -pruozedata <<EOF
use sqoop;
truncate etl_result;
EOF

部分问题总结

报错信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
19/12/26 11:29:41 ERROR tool.ImportTool: Import failed: java.io.IOException: java.lang.ClassNotFoundException: org.apache.hadoop.hive.conf.HiveConf
at org.apache.sqoop.hive.HiveConfig.getHiveConf(HiveConfig.java:50)
at org.apache.sqoop.hive.HiveImport.getHiveArgs(HiveImport.java:392)
at org.apache.sqoop.hive.HiveImport.executeExternalHiveScript(HiveImport.java:379)
at org.apache.sqoop.hive.HiveImport.executeScript(HiveImport.java:337)
at org.apache.sqoop.hive.HiveImport.importTable(HiveImport.java:241)
at org.apache.sqoop.tool.ImportTool.importTable(ImportTool.java:530)
at org.apache.sqoop.tool.ImportTool.run(ImportTool.java:621)
at org.apache.sqoop.Sqoop.run(Sqoop.java:147)
at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:70)
at org.apache.sqoop.Sqoop.runSqoop(Sqoop.java:183)
at org.apache.sqoop.Sqoop.runTool(Sqoop.java:234)
at org.apache.sqoop.Sqoop.runTool(Sqoop.java:243)
at org.apache.sqoop.Sqoop.main(Sqoop.java:252)
Caused by: java.lang.ClassNotFoundException: org.apache.hadoop.hive.conf.HiveConf

解决:将Hive中lib下面的hive* 的jar包拷贝到Sqoop的lib目录即可