Sqoop1 导入与导出数据

本篇博客主要介绍如何使用Sqoop1.x版本来实现数据的导入与导出,笔者使用的版本为Sqoop1.4.6,安装配置请参考博客:
http://blog.csdn.net/hg_harvey/article/details/77803520

官网文档:http://sqoop.apache.org/docs/1.4.6/SqoopUserGuide.html

1.MySQL 导入数据到 HDFS

流程图:

Sqoop1 导入与导出数据_第1张图片

说明:
(1).Sqoop 与数据库进行通信,获取数据库表的元数据信息
(2).Sqoop启动一个Map-Only的MapReduce作业,利用元数据信息并行将数据写入Hadoop

1.数据准备

  • MySQL 中创建数据库sqoop
create database sqoop;
use sqoop;
  • 创建两张表dept及emp
CREATE TABLE DEPT(
    DEPTNO int(2) PRIMARY KEY,
    DNAME VARCHAR(14),
    LOC VARCHAR(13) 
);

表结构:

mysql> desc DEPT;
+--------+-------------+------+-----+---------+-------+
| Field  | Type        | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+-------+
| DEPTNO | int(2)      | NO   | PRI | NULL    |       |
| DNAME  | varchar(14) | YES  |     | NULL    |       |
| LOC    | varchar(13) | YES  |     | NULL    |       |
+--------+-------------+------+-----+---------+-------+
CREATE TABLE EMP(
    EMPNO int(4) PRIMARY KEY,
    ENAME VARCHAR(10),
    JOB VARCHAR(9),
    MGR int(4),
    HIREDATE DATE,
    SAL int(7),
    COMM int(7),
    DEPTNO int(2),
    foreign key(deptno) references DEPT(DEPTNO)
); 

表结构:

mysql> desc EMP;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| EMPNO    | int(4)      | NO   | PRI | NULL    |       |
| ENAME    | varchar(10) | YES  |     | NULL    |       |
| JOB      | varchar(9)  | YES  |     | NULL    |       |
| MGR      | int(4)      | YES  |     | NULL    |       |
| HIREDATE | date        | YES  |     | NULL    |       |
| SAL      | int(7)      | YES  |     | NULL    |       |
| COMM     | int(7)      | YES  |     | NULL    |       |
| DEPTNO   | int(2)      | YES  | MUL | NULL    |       |
+----------+-------------+------+-----+---------+-------+
  • 插入数据

DEPT 表:

INSERT INTO DEPT VALUES
 (10,'ACCOUNTING','NEW YORK');
INSERT INTO DEPT VALUES (20,'RESEARCH','DALLAS');
INSERT INTO DEPT VALUES
 (30,'SALES','CHICAGO');
INSERT INTO DEPT VALUES
 (40,'OPERATIONS','BOSTON');

Sqoop1 导入与导出数据_第2张图片

EMP 表:

INSERT INTO EMP VALUES
(7369,'SMITH','CLERK',7902,'1980-12-17',800,NULL,20);
INSERT INTO EMP VALUES
(7499,'ALLEN','SALESMAN',7698,'1981-2-20',1600,300,30);
INSERT INTO EMP VALUES
(7521,'WARD','SALESMAN',7698,'1981-2-22',1250,500,30);
INSERT INTO EMP VALUES
(7566,'JONES','MANAGER',7839,'1981-4-2',2975,NULL,20);
INSERT INTO EMP VALUES
(7654,'MARTIN','SALESMAN',7698,'1981-9-28',1250,1400,30);
INSERT INTO EMP VALUES
(7698,'BLAKE','MANAGER',7839,'1981-5-1',2850,NULL,30);
INSERT INTO EMP VALUES
(7782,'CLARK','MANAGER',7839,'1981-6-9',2450,NULL,10);
INSERT INTO EMP VALUES
(7788,'SCOTT','ANALYST',7566,'87-7-13',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-9-8',1500,0,30);
INSERT INTO EMP VALUES
(7876,'ADAMS','CLERK',7788,'87-7-13',1100,NULL,20);
INSERT INTO EMP VALUES
(7900,'JAMES','CLERK',7698,'1981-12-3',950,NULL,30);
INSERT INTO EMP VALUES
(7902,'FORD','ANALYST',7566,'1981-12-3',3000,NULL,20);
INSERT INTO EMP VALUES
(7934,'MILLER','CLERK',7782,'1982-1-23',1300,NULL,10);

Sqoop1 导入与导出数据_第3张图片

2.从mysql导入数据到HDFS

导入数据使用import命令,输入如下命令查看帮助说明

$ sqoop help import

输入命令导入数据

sqoop import \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root \
--password P@ssw0rd \
--table EMP -m 1\

访问 http://IP:8088/cluster 查看任务

Sqoop1 导入与导出数据_第4张图片

点击History,查看历史

Sqoop1 导入与导出数据_第5张图片

查看运行结果
默认导入HDFS路径:/user/用户名/表名

$ hadoop fs -ls /user/hadoop/EMP
$ hadoop fs -text /user/hadoop/EMP/part-m-00000

Sqoop1 导入与导出数据_第6张图片

3.sqoop import 命令常用参数使用

(1).导入数据前先删除目录(–delete-target-dir)

如果重复执行上面的命令导入数据到hdfs会报如下错误
Encountered IOException running import job:
org.apache.hadoop.mapred.FileAlreadyExistsException:
Output directory hdfs://hdpcomprs:9000/user/hadoop/EMP already exists

错误原因:hdfs中文件路径已存在
解决方法:
①.手工把存在的目录删除
②.执行导入时,加上参数–delete-target-dir

sqoop import \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root \
--password P@ssw0rd \
--delete-target-dir \
--table EMP -m 1

(2).设置mapreduce作业名称(–mapreduce-job-name)

sqoop import \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root \
--password P@ssw0rd \
--delete-target-dir \
--mapreduce-job-name FromMySQLToHDFS \
--table EMP -m 1

查看mapreduce作业名称

Sqoop1 导入与导出数据_第7张图片

(3).导入数据时指定hdfs路径(–target-dir)

sqoop import \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root \
--password P@ssw0rd \
--delete-target-dir \
--mapreduce-job-name FromMySQLToHDFS \
--target-dir EMP_INFO \
--table EMP -m 1

数据导入到hdfs的路径为:/user/hadoop/EMP_INFO

(4).设置只导入指定列的数据(–columns)

sqoop import \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root \
--password P@ssw0rd \
--delete-target-dir \
--mapreduce-job-name FromMySQLToHDFS \
--target-dir EMP_COLUMN \
--columns "EMPNO,ENAME,JOB,SAL,COMM" \
--table EMP -m 1

运行结果:

$ hadoop fs -ls /user/hadoop/EMP_COLUMN
$ hadoop fs -text /user/hadoop/EMP_COLUMN/part-m-00000

Sqoop1 导入与导出数据_第8张图片

(5).导入数据时设置文件的存储格式

使用参数–as-parquetfile 设置存储格式为parquet格式

sqoop import \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root \
--password P@ssw0rd \
--delete-target-dir \
--mapreduce-job-name FromMySQLToHDFS \
--target-dir EMP_COLUMN_PARQUET \
--columns "EMPNO,ENAME,JOB,SAL,COMM" \
--as-parquetfile \
--table EMP -m 1

导入完成后,在hdfs中可以看到文件的存储格式为parquetfile

$ hadoop fs -ls /user/hadoop/EMP_COLUMN_PARQUET

这里写图片描述

(6).设置导入数据字段与字段、行与行之间的分隔符

设置字段与字段之间的分隔符使用参数–fields-terminated-by,设置行与行之间的分隔符使用–lines-terminated-by

sqoop import \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root \
--password P@ssw0rd \
--delete-target-dir \
--mapreduce-job-name FromMySQLToHDFS \
--target-dir EMP_SPLIT \
--fields-terminated-by '\t' \
--lines-terminated-by '\n' \
--table EMP -m 1

运行结果:

$ hadoop fs -ls /user/hadoop/EMP_SPLIT
$ hadoop fs -text /user/hadoop/EMP_SPLIT/part-m-00000

Sqoop1 导入与导出数据_第9张图片

(7).条件导入

实现需求:将emp表中工资大于2000的员工信息导入到hdfs

  • 方式一:–where
sqoop import \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root --password P@ssw0rd \
--delete-target-dir \
--target-dir EMP_COLUMN_WHERE \
--columns "EMPNO,ENAME,JOB,SAL,COMM" \
--mapreduce-job-name FromMySQLToHDFS \
--where 'SAL>2000' \
--fields-terminated-by '\t' \ 
--lines-terminated-by '\n' \
--table EMP -m 2

命令中-m 写的是2,表示会有两个map,也就是两个输出文件,即执行完成后,在hdfs中会有两个文件

查看结果:

$ hadoop fs -ls /user/hadoop/EMP_COLUMN_WHERE
$ hadoop fs -text /user/hadoop/EMP_COLUMN_WHERE/part-m-00000
$ hadoop fs -text /user/hadoop/EMP_COLUMN_WHERE/part-m-00001

Sqoop1 导入与导出数据_第10张图片

  • 方式二:–query
sqoop import \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root \
--password P@ssw0rd \
--delete-target-dir \
--target-dir EMP_COLUMN_QUERY \
--query 'select * from EMP where SAL>2000' \
--mapreduce-job-name FromMySQLToHDFS \
--fields-terminated-by '\t' \
--lines-terminated-by '\n' \
--table EMP -m 1

执行命令报如下错误:
Cannot specify –query and –table together.
错误原因:在使用–query后,查询条件已经指定了表名,不需要再使用–table参数来指定表名了
解决方法:去掉–table参数

sqoop import \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root \
--password P@ssw0rd \
--delete-target-dir \
--target-dir EMP_COLUMN_QUERY \
--query 'select * from EMP where SAL>2000' \
--mapreduce-job-name FromMySQLToHDFS \
--fields-terminated-by '\t' \
--lines-terminated-by '\n' \
-m 1

修改后再次执行报如下错误:
IOException: Query [select * from EMP where
SAL>2000] must contain ‘$CONDITIONS’ in WHERE clause

解决方法:在where条件后添加 and $CONDITIONS

sqoop import \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root \
--password P@ssw0rd \
--delete-target-dir \
--target-dir EMP_COLUMN_QUERY \
--query 'select * from EMP where SAL>2000 and $CONDITIONS' \
--mapreduce-job-name FromMySQLToHDFS \
--fields-terminated-by '\t' \
--lines-terminated-by '\n' \
-m 1

查看运行结果:

$ hadoop fs -ls /user/hadoop/EMP_COLUMN_QUERY
$ hadoop fs -text /user/hadoop/EMP_COLUMN_QUERY/part-m-00000

Sqoop1 导入与导出数据_第11张图片

–query 不仅支持单表查询,也支持多表查询

实现需求:查询员工编号、名称及员工所属部门导入到hdfs

sqoop import \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root \
--password P@ssw0rd \
--delete-target-dir \
--target-dir EMP_COLUMN_QUERY_JOIN \
--query 'select E.EMPNO,E.ENAME,D.DNAME from EMP E inner join DEPT D on D.DEPTNO = E.DEPTNO and $CONDITIONS' \
--mapreduce-job-name FromMySQLToHDFS \
--fields-terminated-by '\t' \
--lines-terminated-by '\n' \
-m 1

查看运行结果:

$ hadoop fs -ls /user/hadoop/EMP_COLUMN_QUERY_JOIN
$ hadoop fs -text /user/hadoop/EMP_COLUMN_QUERY_JOIN/part-m-00000

Sqoop1 导入与导出数据_第12张图片

(8).导入时将文件作为参数传入(–options-file)

新建文件emp.opt,文件内容如下

import
--connect 
jdbc:mysql://localhost:3306/sqoop 
--username 
root 
--password 
P@ssw0rd
--delete-target-dir 
--target-dir 
EMP_OPTIONS_FILE
--mapreduce-job-name 
FromMySQLToHDFS 
--table 
EMP
-m 
1 

注意:如果使用将文件作为参数,在文件中每个命令参数必须为一行

输入如下命令导入数据到hdfs

sqoop --options-file emp.opt 

查看运行结果:

$ hadoop fs -ls /user/hadoop/EMP_OPTIONS_FILE
$ hadoop fs -text /user/hadoop/EMP_OPTIONS_FILE/part-m-00000

Sqoop1 导入与导出数据_第13张图片

2.HDFS 导出数据到 MySQL

流程图:

Sqoop1 导入与导出数据_第14张图片

说明:
(1).Sqoop与数据库通信,获取数据库表的元数据信息;
(2).将Hadoop上的文件划分成若干个Split,每个Split由一个Map Task进行数据导出操作;

1.HDFS 导出数据到MySQL

导出命令使用export,输入如下命令查看命令帮助说明

$ sqoop help export

导出数据到mysql(mysql 中 没有表 EMP_DEMO)

sqoop export \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root --password P@ssw0rd \
--table EMP_DEMO \
--export-dir /user/hadoop/EMP \
-m 1 

执行命令后报错:
Table ‘sqoop.EMP_DEMO’ doesn’t exist
说明sqoop不会在mysql中自动创建表,在mysql中创建表EMP_DEMO

CREATE TABLE EMP_DEMO(
    EMPNO int(4) PRIMARY KEY,
    ENAME VARCHAR(10),
    JOB VARCHAR(9),
    MGR int(4),
    HIREDATE DATE,
    SAL int(7),
    COMM int(7),
    DEPTNO int(2),
    foreign key(deptno) references DEPT(DEPTNO)
); 

再次执行命令后(如果多次执行导出数据会一致追加到表EMP_DEMO中),运行结果如下

Sqoop1 导入与导出数据_第15张图片

2.sqoop export 命令常用参数使用

导出指定的列(–columns)

sqoop export \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root --password P@ssw0rd \
--table EMP_DEMO \
--columns "EMPNO,ENAME,JOB,SAL,COMM" \
--export-dir /user/hadoop/EMP_COLUMN \
-m 1 

查看结果:只有指定的列中有数据

Sqoop1 导入与导出数据_第16张图片

导出数据时设置字段与字段、行与行之间的分隔符

hdfs中/user/hadoop下EMP_SPLIT文件中的数据是我们前面通过mysql导入的,使用了分隔符,所以在导出时也需要指定分隔符,否则导出不成功。EMP_SPLIT文件内容如下

Sqoop1 导入与导出数据_第17张图片

sqoop export \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root --password P@ssw0rd \
--table EMP_DEMO \
--fields-terminated-by '\t' --lines-terminated-by '\n' \
--export-dir /user/hadoop/EMP_SPLIT \
-m 1 

运行结果:

Sqoop1 导入与导出数据_第18张图片

3.MySQL 导入数据到 Hive

  • 全部导入

实现需求:将mysql中表emp导入到hive中

sqoop import \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root --password P@ssw0rd \
--table EMP \
--delete-target-dir \
--hive-import \
--hive-database db_test --create-hive-table --hive-table emp_import \
-m 1 

运行结果:

Sqoop1 导入与导出数据_第19张图片

注意:
运行完成后在hive中自动创建了一张表emp_import,通过命令查看表的信息,可以看到sal的数据类型为int,实际我们一般都是double类型,所以不建议使用–create-hive-table参数来自动创建hive表,建议手动创建表,再使用命令导入。

  • 部分导入

hive 中 创建表

create table emp_column(
empno int,
ename string,
job string,
mgr int,
hiredate string,
sal double,
comm double,
deptno int
) 
row format delimited fields terminated by '\t' lines terminated by '\n';

Sqoop1 导入与导出数据_第20张图片

执行如下命令,将指定的列导入数据到hive

sqoop import \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root --password P@ssw0rd \
--table EMP \
--delete-target-dir  \
--columns "EMPNO,ENAME,JOB,SAL,COMM" \
--fields-terminated-by '\t' --lines-terminated-by '\n' \
--hive-import --hive-table emp_column --hive-overwrite  \
-m 1

运行结果:

Sqoop1 导入与导出数据_第21张图片

4.Hive 导出数据到 MySQL

实现需求:将hive 表 emp_import 中的数据导出到 Mysql 表 EMP_DEMO

hive 表 emp_import对应hdfs路径:/user/hive/warehouse/db_test.db/emp_import

mysql 中 EMP_DEMO 表结构如下

mysql> desc EMP_DEMO;
+----------+-------------+------+-----+---------+-------+
| Field    | Type        | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+-------+
| EMPNO    | int(4)      | NO   | PRI | NULL    |       |
| ENAME    | varchar(10) | YES  |     | NULL    |       |
| JOB      | varchar(9)  | YES  |     | NULL    |       |
| MGR      | int(4)      | YES  |     | NULL    |       |
| HIREDATE | date        | YES  |     | NULL    |       |
| SAL      | int(7)      | YES  |     | NULL    |       |
| COMM     | int(7)      | YES  |     | NULL    |       |
| DEPTNO   | int(2)      | YES  | MUL | NULL    |       |
+----------+-------------+------+-----+---------+-------+
8 rows in set (0.34 sec)

注意:mysql中日期为date类型,hive中对应的字段为字符串类型,其存储格式必须为:yyyy-mm-dd

导出时指定null字段的填充符,如果不指定会报一个异常NumberFormatException
–input-null-string:如果没有这个选项,那么在字符串类型列中,字符串”null”会被转换成空字符串,所以最好写上这个,指定为’\N’
–input-null-non-string:如果没有这个选项,那么在非字符串类型的列中,空串和”null”都会被看作是null

执行命令导出(相当于hdfs导出到mysql)

sqoop export \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root --password P@ssw0rd \
--table EMP_DEMO \
--export-dir /user/hive/warehouse/db_test.db/emp_import \
--input-fields-terminated-by '\001' \
--input-null-string '\\N' --input-null-non-string '\\N' \
-m 1 

运行结果:

Sqoop1 导入与导出数据_第22张图片

你可能感兴趣的:(Sqoop)