Sqoop实战

目录

一、Sqoop 简介与安装

1.1.Sqoop 简介

1.2.Sqoop原理

1.3.Sqoop安装

1.3.1. 下载并解压

1.3.2.配置环境变量

1.3.3.修改配置

1.3.4.拷贝JDBC驱动

1.3.5.验证Sqoop

1.3.6.测试Sqoop是否能够成功连接数据库

二、Sqoop 的基本使用

2.1.Sqoop 基本命令

2.1.1.查看所有命令

2.1.2.查看某条命令的具体使用方法

2.2.Sqoop一些常用命令及参数

2.2.1.常用命令列举

2.2.2.命令&参数详解

2.3.Sqoop 与 MySQL

2.3.1查询MySQL所有数据库

2.3.2.查询指定数据库中所有数据表

2.4.Sqoop 与 HDFS

2.4.1.MySQL数据导入到HDFS

2.4.2.导入验证

2.4.3.HDFS数据导出到MySQL

2.4.4.脚本打包

2.5.Sqoop 与 Hive

2.5.1 MySQL数据导入到Hive

2.5.2.Hive 导出数据到MySQL

2.6.Sqoop 与 HBase

2.6.1.MySQL导入数据到HBase

2.7.全库导入

2.8.Sqoop 数据过滤

2.8.1 query参数

2.8.2.导入指定列

2.8.3.使用sqoop关键字筛选查询导入数据

2.8.4.增量导入

2.9.类型支持


一、Sqoop 简介与安装

1.1.Sqoop 简介

官网地址:https://sqoop.apache.org/

Sqoop是一个常用的数据迁移工具,主要用于在Hadoop(Hive)与传统的数据库(mysql、postgresql...)之间实现数据的导入与导出:

  • 导入数据:从 MySQL,Oracle,Postgresql 等关系型数据库中导入数据到 HDFS、Hive、HBase 等分布式文件存储系统中;

  • 导出数据:从分布式文件系统中导出数据到关系型数据库中。

Sqoop项目开始于2009年,最早是作为Hadoop的一个第三方模块存在,后来为了让使用者能够快速部署,也为了让开发人员能够更快速的迭代开发,Sqoop独立成为一个Apache项目。

Sqoop2的最新版本是1.99.7。请注意,2与1不兼容,且特征不完整,它并不打算用于生产部署。

1.2.Sqoop原理

  • 将导入或导出命令翻译成mapreduce程序来实现。
  • 在翻译出的mapreduce中主要是对inputformat和outputformat进行定制。

其原理是将执行命令转化成 MapReduce 作业来实现数据的迁移,如下图:

1.3.Sqoop安装

版本选择:目前 Sqoop 有 Sqoop 1 和 Sqoop 2 两个版本,但是截至到目前,官方并不推荐使用 Sqoop 2,因为其与 Sqoop 1 并不兼容,且功能还没有完善,所以这里优先推荐使用 Sqoop 1。

备注:安装Sqoop的前提是已经具备Java和Hadoop的环境。、

1.3.1. 下载并解压

1) 下载地址:http://mirrors.hust.edu.cn/apache/sqoop/1.4.7/

2) 上传安装包sqoop-1.4.7.bin__hadoop-2.6.0-alpha.tar.gz到虚拟机中

3) 解压sqoop安装包到指定目录,如:

$ tar -zxf sqoop-1.4.7.bin__hadoop-2.6.0-alpha.tar.gz -C /opt/module/

1.3.2.配置环境变量

# vim /etc/profile

添加环境变量:

export SQOOP_HOME=/usr/app/sqoop-1.4.7
export PATH=$SQOOP_HOME/bin:$PATH

使得配置的环境变量立即生效:

# source /etc/profile

1.3.3.修改配置

进入安装目录下的 conf/ 目录,拷贝 Sqoop 的环境配置模板 sqoop-env.sh.template

# cp sqoop-env-template.sh sqoop-env.sh

修改 sqoop-env.sh,内容如下 (以下配置中 HADOOP_COMMON_HOME 和 HADOOP_MAPRED_HOME 是必选的,其他的是可选的):

#cdh版
# Set Hadoop-specific environment variables here.
#Set path to where bin/hadoop is available
export HADOOP_COMMON_HOME=/usr/app/hadoop-2.6.0-cdh5.15.2
#Set path to where hadoop-*-core.jar is available
export HADOOP_MAPRED_HOME=/usr/app/hadoop-2.6.0-cdh5.15.2
#set the path to where bin/hbase is available
export HBASE_HOME=/usr/app/hbase-1.2.0-cdh5.15.2
#Set the path to where bin/hive is available
export HIVE_HOME=/usr/app/hive-1.1.0-cdh5.15.2
#Set the path for where zookeper config dir is
export ZOOCFGDIR=/usr/app/zookeeper-3.4.13/conf

#apache原生版
export HADOOP_COMMON_HOME=/opt/module/hadoop-2.7.2
export HADOOP_MAPRED_HOME=/opt/module/hadoop-2.7.2
export HIVE_HOME=/opt/module/hive
export ZOOKEEPER_HOME=/opt/module/zookeeper-3.4.10
export ZOOCFGDIR=/opt/module/zookeeper-3.4.10
export HBASE_HOME=/opt/module/hbase

1.3.4.拷贝JDBC驱动

拷贝jdbc驱动到sqoop的lib目录下,驱动包的下载地址为 https://dev.mysql.com/downloads/connector/j/ ,如:

$ cp mysql-connector-java-5.1.27-bin.jar /opt/module/sqoop-1.4.6.bin__hadoop-2.0.4-alpha/lib/

1.3.5.验证Sqoop

由于已经将 sqoop 的 bin 目录配置到环境变量,直接使用以下命令验证是否配置成功:

# sqoop version

我们也可以通过某一个command来验证sqoop配置是否正确:

$ bin/sqoop help

这里出现的两个 Warning 警告是因为我们本身就没有用到 HCatalog 和 Accumulo,忽略即可。Sqoop 在启动时会去检查环境变量中是否有配置这些软件,如果想去除这些警告,可以修改 bin/configure-sqoop,注释掉不必要的检查。

# Check: If we can't find our dependencies, give up here.
if [ ! -d "${HADOOP_COMMON_HOME}" ]; then
  echo "Error: $HADOOP_COMMON_HOME does not exist!"
  echo 'Please set $HADOOP_COMMON_HOME to the root of your Hadoop installation.'
  exit 1
fi
if [ ! -d "${HADOOP_MAPRED_HOME}" ]; then
  echo "Error: $HADOOP_MAPRED_HOME does not exist!"
  echo 'Please set $HADOOP_MAPRED_HOME to the root of your Hadoop MapReduce installation.'
  exit 1
fi
## Moved to be a runtime check in sqoop.
if [ ! -d "${HBASE_HOME}" ]; then
  echo "Warning: $HBASE_HOME does not exist! HBase imports will fail."
  echo 'Please set $HBASE_HOME to the root of your HBase installation.'
fi
## Moved to be a runtime check in sqoop.
if [ ! -d "${HCAT_HOME}" ]; then
  echo "Warning: $HCAT_HOME does not exist! HCatalog jobs will fail."
  echo 'Please set $HCAT_HOME to the root of your HCatalog installation.'
fi
if [ ! -d "${ACCUMULO_HOME}" ]; then
  echo "Warning: $ACCUMULO_HOME does not exist! Accumulo imports will fail."
  echo 'Please set $ACCUMULO_HOME to the root of your Accumulo installation.'
fi
if [ ! -d "${ZOOKEEPER_HOME}" ]; then
  echo "Warning: $ZOOKEEPER_HOME does not exist! Accumulo imports will fail."
  echo 'Please set $ZOOKEEPER_HOME to the root of your Zookeeper installation.'
fi

1.3.6.测试Sqoop是否能够成功连接数据库

$ bin/sqoop list-databases --connect jdbc:mysql://hadoop102:3306/ --username root --password 000000

出现如下输出:

information_schema
metastore
mysql
test
oozie
performance_schema

成功!!

二、Sqoop 的基本使用

2.1.Sqoop 基本命令

2.1.1.查看所有命令

# sqoop help

2.1.2.查看某条命令的具体使用方法

# sqoop help 命令名

2.2.Sqoop一些常用命令及参数

2.2.1.常用命令列举

这里列出来了一部分Sqoop操作时的常用参数,以供参考,需要深入学习的可以参看对应类的源代码。

序号

命令

说明

1

import

ImportTool

将数据导入到集群

2

export

ExportTool

将集群数据导出

3

codegen

CodeGenTool

获取数据库中某张表数据生成Java并打包Jar

4

create-hive-table

CreateHiveTableTool

创建Hive表

5

eval

EvalSqlTool

查看SQL执行结果

6

import-all-tables

ImportAllTablesTool

导入某个数据库下所有表到HDFS中

7

job

JobTool

用来生成一个sqoop的任务,生成后,该任务并不执行,除非使用命令执行该任务。

8

list-databases

ListDatabasesTool

列出所有数据库名

9

list-tables

ListTablesTool

列出某个数据库下所有表

10

merge

MergeTool

将HDFS中不同目录下面的数据合在一起,并存放在指定的目录中

11

metastore

MetastoreTool

记录sqoop job的元数据信息,如果不启动metastore实例,则默认的元数据存储目录为:~/.sqoop,如果要更改存储目录,可以在配置文件sqoop-site.xml中进行更改。

12

help

HelpTool

打印sqoop帮助信息

13

version

VersionTool

打印sqoop版本信息

2.2.2.命令&参数详解

上面列举了一些Sqoop的常用命令,对于不同的命令,有不同的参数,让我来一一列举说明。

首先来介绍一下公用的参数,所谓公用参数,就是大多数命令都支持的参数。

2.2.2.1.公用参数:数据库连接

序号

参数

说明

1

--connect

连接关系型数据库的URL

2

--connection-manager

指定要使用的连接管理类

3

--driver

Hadoop根目录

4

--help

打印帮助信息

5

--password

连接数据库的密码

6

--username

连接数据库的用户名

7

--verbose

在控制台打印出详细信息

2.2.2.2.公用参数:import

序号

参数

说明

1

--enclosed-by

给字段值前加上指定的字符

2

--escaped-by 

对字段中的双引号加转义符

3

--fields-terminated-by 

设定每个字段是以什么符号作为结束,默认为逗号

4

--lines-terminated-by 

设定每行记录之间的分隔符,默认是\n

5

--mysql-delimiters

Mysql默认的分隔符设置,字段之间以逗号分隔,行之间以\n分隔,默认转义符是\,字段值以单引号包裹。

6

--optionally-enclosed-by 

给带有双引号或单引号的字段值前后加上指定字符。

2.2.2.3.公用参数:export

序号

参数

说明

1

--input-enclosed-by

对字段值前后加上指定字符

2

--input-escaped-by 

对含有转移符的字段做转义处理

3

--input-fields-terminated-by

字段之间的分隔符

4

--input-lines-terminated-by 

行之间的分隔符

5

--input-optionally-enclosed-by 

给带有双引号或单引号的字段前后加上指定字符

2.2.2.4.公用参数:hive

序号

参数

说明

1

--hive-delims-replacement

用自定义的字符串替换掉数据中的\r\n和\013 \010等字符

2

--hive-drop-import-delims

在导入数据到hive时,去掉数据中的\r\n\013\010这样的字符

3

--map-column-hive

生成hive表时,可以更改生成字段的数据类型

4

--hive-partition-key

创建分区,后面直接跟分区名,分区字段的默认类型为string

5

--hive-partition-value

导入数据时,指定某个分区的值

6

--hive-home 

hive的安装目录,可以通过该参数覆盖之前默认配置的目录

7

--hive-import

将数据从关系数据库中导入到hive表中

8

--hive-overwrite

覆盖掉在hive表中已经存在的数据

9

--create-hive-table

默认是false,即,如果目标表已经存在了,那么创建任务失败。

10

--hive-table

后面接要创建的hive表,默认使用MySQL的表名

11

--table

指定关系数据库的表名

公用参数介绍完之后,我们来按照命令介绍命令对应的特有参数。

2.2.2.5.命令&参数:import

将关系型数据库中的数据导入到HDFS(包括Hive,HBase)中,如果导入的是Hive,那么当Hive中没有对应表时,则自动创建。

1) 命令:

如:导入数据到hive中

$ bin/sqoop import \
--connect jdbc:mysql://hadoop002:3306/company \
--username root \
--password 123456 \
--table staff \
--hive-import

如:增量导入数据到hive中,mode=append

append导入:
$ bin/sqoop import \
--connect jdbc:mysql://hadoop002:3306/company \
--username root \
--password 123456 \
--table staff \
--num-mappers 1 \
--fields-terminated-by "\t" \
--target-dir /user/hive/warehouse/staff_hive \
--check-column id \
--incremental append \
--last-value 3

提示:append不能与--hive-等参数同时使用(Append mode for hive imports is not yet supported. Please remove the parameter --append-mode)

如:增量导入数据到hdfs中,mode=lastmodified

先在mysql中建表并插入几条数据:
mysql> create table company.staff_timestamp(id int(4), name varchar(255), sex varchar(255), last_modified timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
mysql> insert into company.staff_timestamp (id, name, sex) values(1, 'AAA', 'female');
mysql> insert into company.staff_timestamp (id, name, sex) values(2, 'BBB', 'female');
先导入一部分数据:
$ bin/sqoop import \
--connect jdbc:mysql://hadoop002:3306/company \
--username root \
--password 123456 \
--table staff_timestamp \
--delete-target-dir \
--m 1
再增量导入一部分数据:
mysql> insert into company.staff_timestamp (id, name, sex) values(3, 'CCC', 'female');
$ bin/sqoop import \
--connect jdbc:mysql://hadoop002:3306/company \
--username root \
--password 123456 \
--table staff_timestamp \
--check-column last_modified \
--incremental lastmodified \
--last-value "2021-09-28 22:20:38" \
--m 1 \
--append

提示:使用lastmodified方式导入数据要指定增量数据是要--append(追加)还是要--merge-key(合并)

提示:last-value指定的值是会包含于增量导入的数据中

2) 参数:

序号

参数

说明

1

--append

将数据追加到HDFS中已经存在的DataSet中,如果使用该参数,sqoop会把数据先导入到临时文件目录,再合并。

2

--as-avrodatafile

将数据导入到一个Avro数据文件中

3

--as-sequencefile

将数据导入到一个sequence文件中

4

--as-textfile

将数据导入到一个普通文本文件中

5

--boundary-query

边界查询,导入的数据为该参数的值(一条sql语句)所执行的结果区间内的数据。

6

--columns 

指定要导入的字段

7

--direct

直接导入模式,使用的是关系数据库自带的导入导出工具,以便加快导入导出过程。

8

--direct-split-size

在使用上面direct直接导入的基础上,对导入的流按字节分块,即达到该阈值就产生一个新的文件

9

--inline-lob-limit

设定大对象数据类型的最大值

10

--m或–num-mappers

启动N个map来并行导入数据,默认4个。

11

--query或--e 

将查询结果的数据导入,使用时必须伴随参--target-dir,--hive-table,如果查询中有where条件,则条件后必须加上$CONDITIONS关键字

12

--split-by

按照某一列来切分表的工作单元,不能与--autoreset-to-one-mapper连用(请参考官方文档)

13

--table 

关系数据库的表名

14

--target-dir

指定HDFS路径

15

--warehouse-dir

与14参数不能同时使用,导入数据到HDFS时指定的目录

16

--where

从关系数据库导入数据时的查询条件

17

--z或--compress

允许压缩

18

--compression-codec

指定hadoop压缩编码类,默认为gzip(Use Hadoop codec default gzip)

19

--null-string

string类型的列如果null,替换为指定字符串

20

--null-non-string

非string类型的列如果null,替换为指定字符串

21

--check-column

作为增量导入判断的列名

22

--incremental 

mode:append或lastmodified

23

--last-value

指定某一个值,用于标记增量导入的位置

2.2.2.6.命令&参数:export

从HDFS(包括Hive和HBase)中奖数据导出到关系型数据库中。

1) 命令:

如:

$ bin/sqoop export \
--connect jdbc:mysql://hadoop002:3306/company \
--username root \
--password 123456 \
--table staff \
--export-dir /user/company \
--input-fields-terminated-by "\t" \
--num-mappers 1

2) 参数:

序号

参数

说明

1

--direct

利用数据库自带的导入导出工具,以便于提高效率

2

--export-dir

存放数据的HDFS的源目录

3

-m或--num-mappers

启动N个map来并行导入数据,默认4个

4

--table

指定导出到哪个RDBMS中的表

5

--update-key

对某一列的字段进行更新操作

6

--update-mode

updateonly

allowinsert(默认)

7

--input-null-string

请参考import该类似参数说明

8

--input-null-non-string

请参考import该类似参数说明

9

--staging-table

创建一张临时表,用于存放所有事务的结果,然后将所有事务结果一次性导入到目标表中,防止错误。

10

--clear-staging-table

如果第9个参数非空,则可以在导出操作执行前,清空临时事务结果表

2.2.2.7.命令&参数:codegen

将关系型数据库中的表映射为8个Java类,在该类中有各列对应的各个字段。

1) 命令:

如:

$ bin/sqoop codegen \
--connect jdbc:mysql://hadoop002:3306/company \
--username root \
--password 123456 \
--table staff \
--bindir /home/admin/Desktop/staff \
--class-name Staff \
--fields-terminated-by "\t"

2) 参数:

序号

参数

说明

1

--bindir 

指定生成的Java文件、编译成的class文件及将生成文件打包为jar的文件输出路径

2

--class-name 

设定生成的Java文件指定的名称

3

--outdir 

生成Java文件存放的路径

4

--package-name

包名,如com.z,就会生成com和z两级目录

5

--input-null-non-string

在生成的Java文件中,可以将null字符串或者不存在的字符串设置为想要设定的值(例如空字符串)

6

--input-null-string

将null字符串替换成想要替换的值(一般与5同时使用)

7

--map-column-java

数据库字段在生成的Java文件中会映射成各种属性,且默认的数据类型与数据库类型保持对应关系。该参数可以改变默认类型,例如:--map-column-java id=long, name=String

8

--null-non-string

在生成Java文件时,可以将不存在或者null的字符串设置为其他值

9

--null-string

在生成Java文件时,将null字符串设置为其他值(一般与8同时使用)

10

--table 

对应关系数据库中的表名,生成的Java文件中的各个属性与该表的各个字段一一对应

2.2.2.8.命令&参数:create-hive-table

生成与关系数据库表结构对应的hive表结构。

1) 命令:

如:

$ bin/sqoop create-hive-table \
--connect jdbc:mysql://hadoop002:3306/company \
--username root \
--password 123456 \
--table staff \
--hive-table hive_staff

2) 参数:

序号

参数

说明

1

--hive-home 

Hive的安装目录,可以通过该参数覆盖掉默认的Hive目录

2

--hive-overwrite

覆盖掉在Hive表中已经存在的数据

3

--create-hive-table

默认是false,如果目标表已经存在了,那么创建任务会失败

4

--hive-table

后面接要创建的hive表

5

--table

指定关系数据库的表名

2.2.2.9.命令&参数:eval

可以快速的使用SQL语句对关系型数据库进行操作,经常用于在import数据之前,了解一下SQL语句是否正确,数据是否正常,并可以将结果显示在控制台。

1) 命令:

如:

$ bin/sqoop eval \
--connect jdbc:mysql://hadoop002:3306/company \
--username root \
--password 123456 \
--query "SELECT * FROM staff"

2) 参数:

序号

参数

说明

1

--query或--e

后跟查询的SQL语句

2.2.2.10.命令&参数:import-all-tables

可以将RDBMS中的所有表导入到HDFS中,每一个表都对应一个HDFS目录

1) 命令:

如:

$ bin/sqoop import-all-tables \
--connect jdbc:mysql://hadoop002:3306/company \
--username root \
--password 123456 \
--warehouse-dir /all_tables

2) 参数:

序号

参数

说明

1

--as-avrodatafile

这些参数的含义均和import对应的含义一致

2

--as-sequencefile

3

--as-textfile

4

--direct

5

--direct-split-size

6

--inline-lob-limit

7

--m或—num-mappers

8

--warehouse-dir

9

-z或--compress

10

--compression-codec

2.2.2.11.命令&参数:job

用来生成一个sqoop任务,生成后不会立即执行,需要手动执行。

1) 命令:

如:

$ bin/sqoop job \
 --create myjob -- import-all-tables \
 --connect jdbc:mysql://hadoop002:3306/company \
 --username root \
 --password 123456
$ bin/sqoop job \
--list
$ bin/sqoop job \
--exec myjob

提示:注意import-all-tables和它左边的--之间有一个空格

提示如果需要连接metastore,则--meta-connect jdbc:hsqldb:hsql://linux01:16000/sqoop

2) 参数:

序号

参数

说明

1

--create 

创建job参数

2

--delete

删除一个job

3

--exec

执行一个job

4

--help

显示job帮助

5

--list

显示job列表

6

--meta-connect

用来连接metastore服务

7

--show

显示一个job的信息

8

--verbose

打印命令运行时的详细信息

提示:在执行一个job时,如果需要手动输入数据库密码,可以做如下优化

<property>
	<name>sqoop.metastore.client.record.password</name>
	<value>true</value>
	<description>If true, allow saved passwords in the metastore.</description>
</property>

2.2.2.12.命令&参数:list-databases

1) 命令:

如:

$ bin/sqoop list-databases \
--connect jdbc:mysql://hadoop002:3306/ \
--username root \
--password 123456

2) 参数:与公用参数一样

2.2.2.13.命令&参数:list-tables

1) 命令:

如:

$ bin/sqoop list-tables \
--connect jdbc:mysql://hadoop002:3306/company \
--username root \
--password 123456

2) 参数:与公用参数一样

2.2.2.14.命令&参数:merge

将HDFS中不同目录下面的数据合并在一起并放入指定目录中

数据环境:

new_staff
1       AAA     male
2       BBB     male
3       CCC     male
4       DDD     male
old_staff
1       AAA     female
2       CCC     female
3       BBB     female
6       DDD     female

提示:上边数据的列之间的分隔符应该为\t,行与行之间的分割符为\n,如果直接复制,请检查之。

1) 命令:

如:

创建JavaBean:
$ bin/sqoop codegen \
--connect jdbc:mysql://hadoop002:3306/company \
--username root \
--password 123456 \
--table staff \
--bindir /home/admin/Desktop/staff \
--class-name Staff \
--fields-terminated-by "\t"

开始合并:
$ bin/sqoop merge \
--new-data /test/new/ \
--onto /test/old/ \
--target-dir /test/merged \
--jar-file /home/admin/Desktop/staff/Staff.jar \
--class-name Staff \
--merge-key id
结果:
1	AAA	MALE
2	BBB	MALE
3	CCC	MALE
4	DDD	MALE
6	DDD	FEMALE

2) 参数:

序号

参数

说明

1

--new-data

HDFS 待合并的数据目录,合并后在新的数据集中保留

2

--onto

HDFS合并后,重复的部分在新的数据集中被覆盖

3

--merge-key

合并键,一般是主键ID

4

--jar-file

合并时引入的jar包,该jar包是通过Codegen工具生成的jar包

5

--class-name

对应的表名或对象名,该class类是包含在jar包中的

6

--target-dir

合并后的数据在HDFS里存放的目录

2.2.2.15.命令&参数:metastore

记录了Sqoop job的元数据信息,如果不启动该服务,那么默认job元数据的存储目录为~/.sqoop,可在sqoop-site.xml中修改。

1) 命令:

如:启动sqoop的metastore服务

$ bin/sqoop metastore

2) 参数:

序号

参数

说明

1

--shutdown

关闭metastore

2.3.Sqoop 与 MySQL

2.3.1查询MySQL所有数据库

1) 确定Mysql服务开启正常

#查看数据库状态:

service mysqld status

#可使用如下命令启动MySQL:

service mysqld start

#或者使用如下命令:

/etc/init.d/mysqld start

#关闭MySQL服务

service mysqld stop

#可使用如下命令重新启动MySQL:

service mysqld restart

#或者使用如下命令:

/etc/init.d/mysqld restart

2) 在Mysql中新建一张表并插入一些数据

$ mysql -uroot -p123456

mysql> create database company;

mysql> create table company.staff(id int(4) primary key not null auto_increment, name varchar(255), sex varchar(255));

mysql> insert into company.staff(name, sex) values('Thomas', 'Male');

mysql> insert into company.staff(name, sex) values('Catalina', 'FeMale');

通常用于 Sqoop 与 MySQL 连通测试:

sqoop list-databases \
--connect jdbc:mysql://hadoop001:3306/ \
--username root \
--password 123456

2.3.2.查询指定数据库中所有数据表

sqoop list-tables \
--connect jdbc:mysql://hadoop002:3306/company \
--username root \
--password 123456

2.4.Sqoop 与 HDFS

2.4.1.MySQL数据导入到HDFS

在Sqoop中,“导入”概念指:从非大数据集群(RDBMS)向大数据集群(HDFS,HIVE,HBASE)中传输数据,叫做:导入,即使用import关键字。

1. 导入命令

示例:导出 MySQL 数据库中的 help_keyword 表到 HDFS 的 /sqoop 目录下,如果导入目录存在则先删除再导入,使用 3 个 map tasks 并行导入。

注:help_keyword 是 MySQL 内置的一张字典表,之后的示例均使用这张表。

sqoop import \
--connect jdbc:mysql://hadoop001:3306/mysql \     
--username root \
--password 123456 \
--table help_keyword \           # 待导入的表
--delete-target-dir \            # 目标目录存在则先删除
--target-dir /sqoop \            # 导入的目标目录
--fields-terminated-by'\t'  \   # 指定导出数据的分隔符
-m 3# 指定并行执行的 map tasks 数量

日志输出如下,可以看到输入数据被平均 split 为三份,分别由三个 map task 进行处理。数据默认以表的主键列作为拆分依据,如果你的表没有主键,有以下两种方案:

  • 添加 -- autoreset-to-one-mapper 参数,代表只启动一个 map task,即不并行执行;
  • 若仍希望并行执行,则可以使用 --split-by  指明拆分数据的参考列。

2.4.2.导入验证

# 查看导入后的目录
hadoop fs -ls  -R /sqoop
# 查看导入内容
hadoop fs -text  /sqoop/part-m-00000

查看 HDFS 导入目录,可以看到表中数据被分为 3 部分进行存储,这是由指定的并行度决定的。

2.4.3.HDFS数据导出到MySQL

在Sqoop中,“导出”概念指:从大数据集群(HDFS,HIVE,HBASE)向非大数据集群(RDBMS)中传输数据,叫做:导出,即使用export关键字。

sqoop export  \
--connect jdbc:mysql://hadoop001:3306/mysql \
--username root \
--password 123456 \
--table help_keyword_from_hdfs \        # 导出数据存储在 MySQL 的 help_keyword_from_hdf 的表中
--export-dir /sqoop  \
--input-fields-terminated-by'\t'\
--m 3

表必须预先创建,建表语句如下:

CREATE TABLE help_keyword_from_hdfs LIKE help_keyword ;

提示:Mysql中如果表不存在,不会自动创建

2.4.4.脚本打包

使用opt格式的文件打包sqoop命令,然后执行

1) 创建一个.opt文件

$ mkdir opt
$ touch opt/job_HDFS2RDBMS.opt

2) 编写sqoop脚本

$ vi opt/job_HDFS2RDBMS.opt

export
--connect
jdbc:mysql://hadoop001:3306/mysql
--username
root
--password
123456
--table
help_keyword_from_hdfs    # 导出数据存储在 MySQL 的 help_keyword_from_hdf 的表中
--num-mappers
3
--export-dir
/sqoop
--input-fields-terminated-by
"\t"

3) 执行该脚本

$ bin/sqoop --options-file opt/job_HDFS2RDBMS.opt

2.5.Sqoop 与 Hive

2.5.1 MySQL数据导入到Hive

Sqoop 导入数据到 Hive 是通过先将数据导入到 HDFS 上的临时目录,然后再将数据从 HDFS 上 Load 到 Hive 中,最后将临时目录删除。可以使用 target-dir 来指定临时目录。

1. 导入命令

sqoop import \
--connect jdbc:mysql://hadoop001:3306/mysql \
--username root \
--password 123456 \
--table help_keyword \        # 待导入的表     
--delete-target-dir \         # 如果临时目录存在删除
--target-dir /sqoop_hive  \   # 临时目录位置
--hive-database sqoop_test \  # 导入到 Hive 的 sqoop_test 数据库,数据库需要预先创建。不指定则默认为 default 库
--hive-import \               # 导入到 Hive
--hive-overwrite \            # 如果 Hive 表中有数据则覆盖,这会清除表中原有的数据,然后再写入
-m 3# 并行度

导入到 Hive 中的 sqoop_test 数据库需要预先创建,不指定则默认使用 Hive 中的 default 库。

# 查看 hive 中的所有数据库
 hive>  SHOW DATABASES;
# 创建 sqoop_test 数据库
 hive>  CREATE DATABASE sqoop_test;

2. 导入验证

# 查看 sqoop_test 数据库的所有表
 hive>  SHOW  TABLES  IN  sqoop_test;
# 查看表中数据
 hive> SELECT * FROM sqoop_test.help_keyword;

3. 可能出现的问题

如果执行报错 java.io.IOException: java.lang.ClassNotFoundException: org.apache.hadoop.hive.conf.HiveConf,则需将 Hive 安装目录下 lib 下的 hive-exec-**.jar 放到 sqoop 的 lib 。

[root@hadoop001 lib]# ll hive-exec-*
-rw-r--r--.1110640011963203111月1321:45 hive-exec-1.1.0-cdh5.15.2.jar
[root@hadoop001 lib]# cp hive-exec-1.1.0-cdh5.15.2.jar  ${SQOOP_HOME}/lib

2.5.2.Hive 导出数据到MySQL

由于 Hive 的数据是存储在 HDFS 上的,所以 Hive 导入数据到 MySQL,实际上就是 HDFS 导入数据到 MySQL。

1.查看Hive表在HDFS的存储位置

# 进入对应的数据库
hive>use sqoop_test;
# 查看表信息
hive> desc formatted help_keyword;

Location 属性为其存储位置

这里可以查看一下这个目录,文件结构如下:

2.执行导出命令

sqoop export  \
--connect jdbc:mysql://hadoop001:3306/mysql \
--username root \
--password 123456 \
--table help_keyword_from_hive \
--export-dir /user/hive/warehouse/sqoop_test.db/help_keyword  \
-input-fields-terminated-by'\001' \             # 需要注意的是 hive 中默认的分隔符为 \001
--m 3

MySQL 中的表需要预先创建:

CREATE TABLE help_keyword_from_hive LIKE help_keyword ;

2.6.Sqoop 与 HBase

本小节只讲解从 RDBMS 导入数据到 HBase,因为暂时没有命令能够从 HBase 直接导出数据到 RDBMS。

2.6.1.MySQL导入数据到HBase

1. 导入数据

将 help_keyword 表中数据导入到 HBase 上的 help_keyword_hbase 表中,使用原表的主键 help_keyword_id 作为 RowKey,原表的所有列都会在 keywordInfo 列族下,目前只支持全部导入到一个列族下,不支持分别指定列族。

sqoop import \
--connect jdbc:mysql://hadoop001:3306/mysql \
--username root \
--password 123456 \
--table help_keyword \              # 待导入的表
--hbase-table help_keyword_hbase \  # hbase 表名称,表需要预先创建
--column-family keywordInfo \       # 所有列导入到 keywordInfo 列族下 
--hbase-row-key help_keyword_id     # 使用原表的 help_keyword_id 作为 RowKey

导入的 HBase 表需要预先创建:

# 查看所有表
hbase> list
# 创建表
hbase> create 'help_keyword_hbase','keywordInfo'
# 查看表信息
hbase> desc 'help_keyword_hbase'

2. 导入验证

使用 scan 查看表数据:

提示:sqoop1.4.6只支持HBase1.0.1之前的版本的自动创建HBase表的功能

2.7.全库导入

Sqoop 支持通过 import-all-tables 命令进行全库导入到 HDFS/Hive,但需要注意有以下两个限制:

  • 所有表必须有主键;或者使用 --autoreset-to-one-mapper,代表只启动一个 map task;
  • 你不能使用非默认的分割列,也不能通过 WHERE 子句添加任何限制。

第二点解释得比较拗口,这里列出官方原本的说明:

  • You must not intend to use non-default splitting column, nor impose any conditions via a WHERE clause.

全库导入到 HDFS:

sqoop import-all-tables \
--connect jdbc:mysql://hadoop001:3306/数据库名 \
--username root \
--password 123456 \
--warehouse-dir  /sqoop_all \     # 每个表会单独导出到一个目录,需要用此参数指明所有目录的父目录
--fields-terminated-by'\t'  \
-m 3

全库导入到 Hive:

sqoop import-all-tables -Dorg.apache.sqoop.splitter.allow_text_splitter=true \
--connect jdbc:mysql://hadoop001:3306/数据库名 \
--username root \
--password 123456 \
--hive-database sqoop_test \         # 导出到 Hive 对应的库   
--hive-import \
--hive-overwrite \
-m 3

2.8.Sqoop 数据过滤

2.8.1 query参数

Sqoop 支持使用 query 参数定义查询 SQL,从而可以导出任何想要的结果集。使用示例如下:

sqoop import \
--connect jdbc:mysql://hadoop001:3306/mysql \
--username root \
--password 123456 \
--query 'select * from help_keyword where  $CONDITIONS and  help_keyword_id < 50' \  
--delete-target-dir \            
--target-dir /sqoop_hive  \ 
--hive-database sqoop_test \           # 指定导入目标数据库 不指定则默认使用 Hive 中的 default 库
--hive-table filter_help_keyword \     # 指定导入目标表
--split-by help_keyword_id \           # 指定用于 split 的列      
--hive-import \                        # 导入到 Hive
--hive-overwrite \                     、
-m 3

在使用 query 进行数据过滤时,需要注意以下三点:

  • 必须用 --hive-table 指明目标表;
  • 如果并行度 -m 不为 1 或者没有指定 --autoreset-to-one-mapper,则需要用 --split-by 指明参考列;
  • SQL 的 where 字句必须包含 $CONDITIONS,这是固定写法,作用是动态替换。如果query后使用的是双引号,则$CONDITIONS前必须加转移符,防止shell识别为自己的变量。

2.8.2.导入指定列

$ bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 123456 \
--target-dir /user/company \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t" \
--columns id,sex \
--table staff

提示:columns中如果涉及到多列,用逗号分隔,分隔时不要添加空格

2.8.3.使用sqoop关键字筛选查询导入数据

$ bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 123456 \
--target-dir /user/company \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t" \
--table staff \
--where "id=1"

2.8.4.增量导入

sqoop import \
--connect jdbc:mysql://hadoop001:3306/mysql \
--username root \
--password 123456 \
--table help_keyword \
--target-dir /sqoop_hive  \
--hive-database sqoop_test \         
--incremental  append  \             # 指明模式
--check-column  help_keyword_id \    # 指明用于增量导入的参考列
--last-value 300  \                  # 指定参考列上次导入的最大值
--hive-import \   
-m 3

incremental 参数有以下两个可选的选项:

  • append:要求参考列的值必须是递增的,所有大于 last-value 的值都会被导入;
  • lastmodified:要求参考列的值必须是 timestamp 类型,且插入数据时候要在参考列插入当前时间戳,更新数据时也要更新参考列的时间戳,所有时间晚于 last-value 的数据都会被导入。

备注:

  • append不能与--hive-等参数同时使用(Append mode for hive imports is not yet supported. Please remove the parameter --append-mode)
  • 使用lastmodified方式导入数据要指定增量数据是要--append(追加)还是要--merge-key(合并)
  • last-value指定的值是会包含于增量导入的数据中

通过上面的解释我们可以看出来,其实 Sqoop 的增量导入并没有太多神奇的地方,就是依靠维护的参考列来判断哪些是增量数据。当然我们也可以使用上面介绍的 query 参数来进行手动的增量导出,这样反而更加灵活。

2.9.类型支持

Sqoop 默认支持数据库的大多数字段类型,但是某些特殊类型是不支持的。遇到不支持的类型,程序会抛出异常

Hive does not support the SQL type for column xxx

,此时可以通过下面两个参数进行强制类型转换:

  • —map-column-java\ :重写 SQL 到 Java 类型的映射;
  • —map-column-hive \ : 重写 Hive 到 Java 类型的映射。

示例如下,将原先 id 字段强制转为 String 类型,value 字段强制转为 Integer 类型:

$ sqoop import...--map-column-java id=String,value=Integer

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大数据翻身

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值