Sqoop 教程

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u011026329/article/details/79184178

一、Sqoop 简介

Sqoop是Hadoop和关系数据库服务器之间传送数据的一种工具。它是用来从关系数据库如:MySQL,Oracle到Hadoop的HDFS,并从Hadoop的文件系统导出数据到关系数据库。

传统的应用管理系统,也就是与关系型数据库的使用RDBMS应用程序的交互,是产生大数据的来源之一。这样大的数据,由关系数据库生成的,存储在关系数据库结构关系数据库服务器。

当大数据存储器和分析器,如MapReduce, Hive, HBase, Cassandra, Pig等,Hadoop的生态系统等应运而生图片,它们需要一个工具来用的导入和导出的大数据驻留在其中的关系型数据库服务器进行交互。在这里,Sqoop占据着Hadoop生态系统提供关系数据库服务器和Hadoop HDFS之间的可行的互动。

Sqoop:“SQL 到 Hadoop 和 Hadoop 到SQL”

Sqoop是Hadoop和关系数据库服务器之间传送数据的一种工具。它是用来从关系数据库如MySQL,Oracle到Hadoop的HDFS从Hadoop文件系统导出数据到关系数据库。它是由Apache软件基金会提供。

Sqoop是怎么样工作的?

下图描述了Sqoop的工作流程。

这里写图片描述

Sqoop导入

导入工具从RDBMS到HDFS导入单个表。表中的每一行被视为HDFS的记录。所有记录被存储在文本文件的文本数据或者在Avro和序列文件的二进制数据。

Sqoop导出

导出工具从HDFS导出一组文件到一个RDBMS。作为输入到Sqoop文件包含记录,这被称为在表中的行。那些被读取并解析成一组记录和分隔使用用户指定的分隔符。

二、Sqoop安装

安装 Cloudera Manager 中的CDH时,已经自动安装了Sqoop

但是在 Cloudera Manager5.12.1 中启动 Sqoop 报错:

[root@master ~]# sqoop help
Warning: /opt/cloudera/parcels/CDH-5.12.1-1.cdh5.12.1.p0.3/bin/../lib/sqoop/../accumulo does not exist! Accumulo imports will fail.
Please set $ACCUMULO_HOME to the root of your Accumulo installation.
17/09/19 17:24:14 FATAL conf.Configuration: error parsing conf core-default.xml
javax.xml.parsers.ParserConfigurationException: Feature 'http://apache.org/xml/features/xinclude' is not recognized.

解决方法:

/usr/bin/sqoop 中修改:

SQOOP_JARS=`ls -f /var/lib/sqoop/*.jar /usr/share/java/*.jar 2>/dev/null`
修改为:
SQOOP_JARS=`ls -f /opt/cloudera/parcels/CDH/lib/sqoop/*.jar 2>/dev/null`

三、Sqoop导入

工具通用选项

import和export工具有些通用的选项,如下表所示:

选项 含义说明
–connect 指定JDBC连接字符串
–connection-manager 指定要使用的连接管理器类
–driver 指定要使用的JDBC驱动类
–hadoop-mapred-home 指定$HADOOP_MAPRED_HOME路径
–help 打印用法帮助信息
–password-file 设置用于存放认证的密码信息文件的路径
-P 从控制台读取输入的密码
–password 设置认证密码
–username 设置认证用户名
–verbose 打印详细的运行信息
–connection-param-file 可选,指定存储数据库连接参数的属性文件

import工具,是将HDFS平台外部的结构化存储系统中的数据导入到Hadoop平台,便于后续分析。我们先看一下import工具的基本选项及其含义,如下表所示:

选项 含义说明
–append 将数据追加到HDFS上一个已存在的数据集上
–as-avrodatafile 将数据导入到Avro数据文件
–as-sequencefile 将数据导入到SequenceFile
–as-textfile 将数据导入到普通文本文件(默认)
–boundary-query 边界查询,用于创建分片(InputSplit)
–columns 从表中导出指定的一组列的数据
–delete-target-dir 如果指定目录存在,则先删除掉
–direct 使用直接导入模式(优化导入速度)
–direct-split-size 分割输入stream的字节大小(在直接导入模式下)
–fetch-size 从数据库中批量读取记录数
–inline-lob-limit 设置内联的LOB对象的大小
-m,–num-mappers 使用n个map任务并行导入数据
-e,–query 导入的查询语句
–split-by 指定按照哪个列去分割数据
–table 导入的源表表名
–target-dir 导入HDFS的目标路径
–warehouse-dir HDFS存放表的根路径
–where 指定导出时所使用的查询条件
-z,–compress 启用压缩
–compression-codec 指定Hadoop的codec方式(默认gzip)
–null-string 如果指定列为字符串类型,使用指定字符串替换值为null的该类列的值
–null-non-string 如果指定列为非字符串类型,使用指定字符串替换值为null的该类列的值

语法

下面的语法用于将数据导入HDFS。

# sqoop import (generic-args) (import-args) 
# sqoop-import (generic-args) (import-args)

示例

让我们以命名为emp, emp_add和emp_contact,这是一个在MySQL数据库服务器名为userdb 数据库的一个例子。

三个表及其数据如下。

表emp:

MariaDB [(none)]> create database userdb;
Query OK, 1 row affected (0.00 sec)

MariaDB [(none)]> use userdb;
Database changed

MariaDB [userdb]> create table emp( 
    id int(4) not null, 
    name varchar(10) not null, 
    deg varchar(20) not null, 
    salary int(5) not null, 
    dept varchar(2) not null, 
    primary key (`id`));

MariaDB [userdb]> insert into emp(id,name,deg,salary,dept) values(1201,'gopal','manager',50000,'TP');
MariaDB [userdb]> insert into emp(id,name,deg,salary,dept) values(1202,'manisha','Proof reader',50000,'TP');
MariaDB [userdb]> insert into emp(id,name,deg,salary,dept) values(1203,'khalil','php dev',30000,'AC');
MariaDB [userdb]> insert into emp(id,name,deg,salary,dept) values(1204,'prasanth','php dev',30000,'AC');
MariaDB [userdb]> insert into emp(id,name,deg,salary,dept) values(1205,'kranthi','admin',20000,'TP');

MariaDB [userdb]> select * from emp;
+------+----------+--------------+--------+------+
| id   | name     | deg          | salary | dept |
+------+----------+--------------+--------+------+
| 1201 | gopal    | manager      |  50000 | TP   |
| 1202 | manisha  | Proof reader |  50000 | TP   |
| 1203 | khalil   | php dev      |  30000 | AC   |
| 1204 | prasanth | php dev      |  30000 | AC   |
| 1205 | kranthi  | admin        |  20000 | TP   |
+------+----------+--------------+--------+------+

表emp_add:

MariaDB [userdb]> create table emp_addr(
    -> id int(4) not null,
    -> hno varchar(4) not null,
    -> street varchar(20) not null,
    -> city varchar(20) not null,
    -> primary key (`id`));
Query OK, 0 rows affected (0.04 sec)

MariaDB [userdb]> insert into emp_addr(id,hno,street,city) values(1201,'288A','vgiri','jublee');
Query OK, 1 row affected (0.01 sec)

MariaDB [userdb]> insert into emp_addr(id,hno,street,city) values(1202,'108I','aoc','sec-bad');
Query OK, 1 row affected (0.00 sec)

MariaDB [userdb]> insert into emp_addr(id,hno,street,city) values(1203,'144Z','pgutta','hyd');
Query OK, 1 row affected (0.01 sec)

MariaDB [userdb]> insert into emp_addr(id,hno,street,city) values(1204,'78B','old city','sec-bad');
Query OK, 1 row affected (0.02 sec)

MariaDB [userdb]> insert into emp_addr(id,hno,street,city) values(1205,'720X','hitec','sec-bad');
Query OK, 1 row affected (0.01 sec)

MariaDB [userdb]> select * from emp_addr;
+------+------+----------+---------+
| id   | hno  | street   | city    |
+------+------+----------+---------+
| 1201 | 288A | vgiri    | jublee  |
| 1202 | 108I | aoc      | sec-bad |
| 1203 | 144Z | pgutta   | hyd     |
| 1204 | 78B  | old city | sec-bad |
| 1205 | 720X | hitec    | sec-bad |
+------+------+----------+---------+
5 rows in set (0.00 sec)

表emp_contact:

MariaDB [userdb]> create table emp_contact(
    -> id int(4) not null,
    -> phno varchar(20) not null,
    -> email varchar(20) not null,
    -> primary key (`id`));
Query OK, 0 rows affected (0.04 sec)

MariaDB [userdb]> insert into emp_contact(id,phno,email) values(1201,'2356742','gopal@tp.com');
Query OK, 1 row affected (0.00 sec)

MariaDB [userdb]> insert into emp_contact(id,phno,email) values(1202,'1661663','manisha@tp.com');
Query OK, 1 row affected (0.02 sec)

MariaDB [userdb]> insert into emp_contact(id,phno,email) values(1203,'8887776','khalil@tp.com');
Query OK, 1 row affected (0.01 sec)

MariaDB [userdb]> insert into emp_contact(id,phno,email) values(1204,'9988774','prasanth@ac.com');
Query OK, 1 row affected (0.05 sec)

MariaDB [userdb]> insert into emp_contact(id,phno,email) values(1205,'1231231','kranthi@ac.com');
Query OK, 1 row affected (0.01 sec)

MariaDB [userdb]> select * from emp_contact;
+------+---------+-----------------+
| id   | phno    | email           |
+------+---------+-----------------+
| 1201 | 2356742 | gopal@tp.com    |
| 1202 | 1661663 | manisha@tp.com  |
| 1203 | 8887776 | khalil@tp.com   |
| 1204 | 9988774 | prasanth@ac.com |
| 1205 | 1231231 | kranthi@ac.com  |
+------+---------+-----------------+
5 rows in set (0.00 sec)

导入表

Sqoop工具 import 是用来从表中导入表数据到Hadoop的文件系统作为文本文件或二进制文件。

下面的命令用于从MySQL数据库服务器中的emp表导入HDFS。

# sqoop import \
--connect jdbc:mysql://master/userdb \
--username root \
--password 123456 \
--table emp --m 1

为了验证在HDFS导入的数据,请使用以下命令。
emp表的数据和字段之间用逗号(,)表示。

[root@master ~]# hdfs dfs -cat /user/root/emp/*
1201,gopal,manager,50000,TP
1202,manisha,Proof reader,50000,TP
1203,khalil,php dev,30000,AC
1204,prasanth,php dev,30000,AC
1205,kranthi,admin,20000,TP

导入到目标目录

在导入表数据到HDFS使用Sqoop导入工具,我们可以指定目标目录。

以下是指定目标目录选项的Sqoop导入命令的语法。

--target-dir <new or exist directory in HDFS>

下面的命令是用来导入emp_add表数据到 /queryresult 目录。

# sqoop import \
--connect jdbc:mysql://master/userdb \
--username root \
--password 123456 \
--table emp_addr \
--m 1 \
--target-dir /queryresult

下面的命令是用来验证 /queryresult 目录中 emp_add表导入的数据形式。

[root@master ~]# hdfs dfs -cat /queryresult/*
1201,288A,vgiri,jublee
1202,108I,aoc,sec-bad
1203,144Z,pgutta,hyd
1204,78B,old city,sec-bad
1205,720X,hitec,sec-bad

表数据导入子集

我们可以导入表的使用Sqoop导入工具,where 子句的一个子集。它执行在各自的数据库服务器相应的SQL查询,并将结果存储在HDFS的目标目录。

where子句的语法如下。

--where <condition>

下面的命令用来导入emp_add表数据的子集。子集查询检索员工ID和地址,居住城市为:Secunderabad

# sqoop import \
--connect jdbc:mysql://master/userdb \
--username root \
--password 123456 \
--table emp_addr \
--m 1 \
--where "city ='sec-bad'" \
--target-dir /wherequery

下面的命令用来验证数据从emp_add表导入/wherequery目录

[root@master ~]# hdfs dfs -cat /wherequery/*
1202,108I,aoc,sec-bad
1204,78B,old city,sec-bad
1205,720X,hitec,sec-bad

增量导入

增量导入是仅导入新添加的表中的行的技术。它需要添加 incremental, check-column, 和 last-value 选项来执行增量导入。

下面的语法用于Sqoop导入命令增量选项。

--incremental <mode>
--check-column <column name>
--last-value <last check column value>

让我们假设新添加的数据转换成emp表如下:

// 1206, satish p, grp des, 20000, GR

MariaDB [dbtaobao]> insert into userdb.emp(id,name,deg,salary,dept)
    -> values(1206,'satish p','grp des',20000,'GR');
Query OK, 1 row affected (0.01 sec)

下面的命令用于在EMP表执行增量导入。

# sqoop import \
--connect jdbc:mysql://master/userdb \
--username root \
--password 123456 \
--table emp \
--m 1 \
--incremental append \
--check-column id \
--last-value 1205

以下命令用于从emp表导入HDFS emp/ 目录的数据验证。

[root@master ~]# hdfs dfs -cat /user/root/emp/*
1201,gopal,manager,50000,TP
1202,manisha,Proof reader,50000,TP
1203,khalil,php dev,30000,AC
1204,prasanth,php dev,30000,AC
1205,kranthi,admin,20000,TP
1206,satish p,grp des,20000,GR

下面的命令是从表emp 用来查看修改或新添加的行

[root@master ~]# hdfs dfs -ls /user/root/emp
Found 3 items
-rw-r--r--   3 root supergroup          0 2017-09-19 18:31 /user/root/emp/_SUCCESS
-rw-r--r--   3 root supergroup        151 2017-09-19 18:31 /user/root/emp/part-m-00000
-rw-r--r--   3 root supergroup         31 2017-09-19 19:00 /user/root/emp/part-m-00001

[root@master ~]# hdfs dfs -cat /user/root/emp/part-m-00001
1206,satish p,grp des,20000,GR

Sqoop导入所有表

本章介绍如何导入RDBMS数据库中的所有表到HDFS。每个表的数据存储在一个单独的目录,目录名与表名相同。

语法

以下语法用于导入所有表。

$ sqoop import-all-tables (generic-args) (import-args) 
$ sqoop-import-all-tables (generic-args) (import-args)

示例

以下是从USERDB数据库导入的所有表的一个例子。数据库USERDB包含表的列表如下。

MariaDB [userdb]> show tables;
+------------------+
| Tables_in_userdb |
+------------------+
| emp              |
| emp_addr         |
| emp_contact      |
+------------------+

下面的命令用于从USERDB数据库中导入所有的表。

# sqoop import-all-tables \
--connect jdbc:mysql://master/userdb \
--username root
--password 123456

注:import-all-tables,它是强制性的,在该数据库中的每个表必须有一个主键字段。

下面的命令用于验证USERDB数据库的所有表数据到HDFS

[root@master ~]# hdfs dfs -ls /user/root
drwxr-xr-x   - root supergroup          0 2017-09-19 22:01 /user/root/emp
drwxr-xr-x   - root supergroup          0 2017-09-19 22:01 /user/root/emp_addr
drwxr-xr-x   - root supergroup          0 2017-09-19 22:01 /user/root/emp_contact

Sqoop 导出

本章介绍如何将数据从HDFS导出到RDBMS数据库。目标表必须存在于目标数据库中。这是作为输入到Sqoop的文件包含记录,这被称为在表中的行。那些被读取并解析成一组记录和分隔与用户指定的分隔符。

默认的操作是从输入文件到数据库表,使用INSERT语句插入所有记录。在更新模式,Sqoop生成替换现有记录到数据库的UPDATE语句。

语法

以下是export命令语法。

# sqoop export (generic-args) (export-args) 
# sqoop-export (generic-args) (export-args)

export工具,是将HDFS平台的数据,导出到外部的结构化存储系统中,可能会为一些应用系统提供数据支持。我们看一下export工具的基本选项及其含义,如下表所示:

|选项|含义说明|
|:—|:—|
|–export-dir

|导出过程中HDFS源路径|
|–table |导出的目的表名称 |
|-m,–num-mappers |使用n个map任务并行导出 |
|–validate |启用数据副本验证功能,仅支持单表拷贝,可以指定验证使用的实现类 |
|–validation-threshold |指定验证门限所使用的类 |
|–direct|使用直接导出模式(优化速度) |
|–call |导出数据调用的指定存储过程名 |
|–update-key |更新参考的列名称,多个列名使用逗号分隔 |
|–update-mode |指定更新策略,包括:updateonly(默认)、allowinsert |
|–input-null-string |使用指定字符串,替换字符串类型值为null的列 |
|–input-null-non-string |使用指定字符串,替换非字符串类型值为null的列 |
|–staging-table |在数据导出到数据库之前,数据临时存放的表名称 |
|–clear-staging-table|清除工作区中临时存放的数据 |
|–batch|使用批量模式导出 |

示例

在HDFS文件中的员工数据的一个例子。员工数据是在HDFS的 /user/root/emp/目录的 emp_data 文件中。所述 emp_data 如下。

1201,gopal,manager,50000,TP
1202,manisha,preader,50000,TP
1203,kalil,php dev,30000,AC
1204,prasanth,php dev,30000,AC
1205,kranthi,admin,20000,TP
1206,satish p,grp des,20000,GR

注意:逗号后面不能有空格

下面的查询被用来创建MySQL命令行表 employee

MariaDB [userdb]> create database db;
Query OK, 1 row affected (0.00 sec)

MariaDB [userdb]> use db;
Database changed
MariaDB [db]> create table employee(
    -> id int not null primary key,
    -> name varchar(20),
    -> deg varchar(20),
    -> salary int,
    -> dept varchar(10));
Query OK, 0 rows affected (0.03 sec)

下面的命令是用来导出表数据(这是在HDFS emp_data文件)到MySQL数据库服务器DB数据库的employee表中。

# sqoop export \
--connect jdbc:mysql://master/db \
--username root \
--password 123456 \
--table employee \ 
--export-dir /user/root/emp/emp_data

下面的命令是用来验证表mysql命令行。

MariaDB [db]> select * from employee;
+------+----------+---------+--------+------+
| id   | name     | deg     | salary | dept |
+------+----------+---------+--------+------+
| 1201 | gopal    | manager |  50000 | TP   |
| 1202 | manisha  | preader |  50000 | TP   |
| 1203 | kalil    | php dev |  30000 | AC   |
| 1204 | prasanth | php dev |  30000 | AC   |
| 1205 | kranthi  | admin   |  20000 | TP   |
| 1206 | satish p | grp des |  20000 | GR   |
+------+----------+---------+--------+------+

展开阅读全文

没有更多推荐了,返回首页