Sqoop数据迁移工具从入门到精通

一、前言

在大数据开发的学习过程中,我们经常会遇到这样的场景:关系型数据库(MySQL、Oracle等)中存储着大量的业务数据,需要将这些数据迁移到Hadoop生态(HDFS、Hive、HBase)中进行离线分析;或者将Hadoop中分析后的结果数据导回关系型数据库供业务系统使用

手动编写JDBC代码进行数据迁移?效率太低且容易出错。这时候就需要一款专业的数据迁移工具------Sqoop

本文将结合我在大数据创新编程课程 中的学习经验,从Sqoop的安装配置讲起,深入讲解RDBMS与Hadoop之间的双向数据迁移,涵盖全部导入、查询导入、增量导入、Hive/HBase导入、数据导出以及脚本打包等完整实战案例。


二、Sqoop概述

2.1 什么是Sqoop?

SqoopSQL To Hadoop )是一款开源的数据迁移工具,主要用于在Hadoop(Hive)与传统的关系型数据库(MySQL、Oracle、PostgreSQL等)之间进行数据的传递

  • ✅ 可以将关系型数据库中的数据导入到Hadoop的HDFS中
  • ✅ 可以将HDFS中的数据导出到关系型数据库中

2.2 Sqoop的发展历史

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

⚠️ 重要提示 :Sqoop2的最新版本是1.99.7,但2与1不兼容且特征不完整 ,不建议用于生产环境。本文及生产环境均使用Sqoop 1.4.6版本。

2.3 Sqoop工作原理

Sqoop的核心原理非常简单:将导入或导出命令翻译成MapReduce程序来实现

复制代码
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  用户输入命令    │────▶│  Sqoop解析命令   │────▶│ 生成MapReduce  │
│  (import/export)│     │  (翻译为MR程序)   │     │  Job并提交执行  │
└─────────────────┘     └─────────────────┘     └─────────────────┘
                                                        │
                                                        ▼
                                               ┌─────────────────┐
                                               │  定制InputFormat │
                                               │  (从MySQL读取)   │
                                               │  定制OutputFormat│
                                               │  (写入HDFS/MySQL)│
                                               └─────────────────┘

在翻译出的MapReduce中,主要是对InputFormat (从MySQL读取到Hive/HBase)和OutputFormat(从HDFS读取到MySQL)进行定制。


三、Sqoop安装与环境配置

3.1 安装前提

安装Sqoop前,必须确保以下环境已就绪:

依赖 版本要求 说明
Java JDK 1.8+ Sqoop基于Java开发
Hadoop 2.x / 3.x 需要Hadoop环境支持MapReduce
Hive 3.x(可选) 如需导入Hive则需要
HBase 2.x(可选) 如需导入HBase则需要

💡 注意 :Sqoop类似于Flume,它不需要常驻进程(没有bin/sbin启动文件),只有在执行任务时才启动,执行完就退出。

3.2 下载并解压

bash 复制代码
# 1. 下载地址(以1.4.6版本为例)
wget http://mirrors.hust.edu.cn/apache/sqoop/1.4.6/sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz

# 2. 上传安装包到虚拟机并解压到指定目录
tar -zxf sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz -C /opt/module/

3.3 修改配置文件

Sqoop的配置文件位于安装目录下的conf文件夹中。

步骤1:重命名配置文件
bash 复制代码
cd /opt/module/sqoop-1.4.6.bin__hadoop-2.0.4-alpha/conf/
mv sqoop-env-template.sh sqoop-env.sh
步骤2:修改sqoop-env.sh
bash 复制代码
vim sqoop-env.sh

根据你的实际环境路径,添加以下内容:

bash 复制代码
# ============================================
# Sqoop环境变量配置
# ============================================

# Hadoop Common模块路径
export HADOOP_COMMON_HOME=/opt/module/hadoop-3.1.3

# Hadoop MapReduce模块路径(通常与HADOOP_COMMON_HOME相同)
export HADOOP_MAPRED_HOME=/opt/module/hadoop-3.1.3

# Hive安装路径(如需要导入Hive)
export HIVE_HOME=/opt/module/hive-3.1.2/

# ZooKeeper安装路径(如需要)
export ZOOKEEPER_HOME=/opt/module/zookeeper-3.7.1/
export ZOOCFGDIR=/opt/module/zookeeper-3.7.1/

# HBase安装路径(如需要导入HBase)
export HBASE_HOME=/opt/module/hbase-2.4.15/

3.4 拷贝JDBC驱动

Sqoop需要通过JDBC连接MySQL,因此需要将MySQL的JDBC驱动包拷贝到Sqoop的lib目录:

bash 复制代码
cp mysql-connector-java-5.1.27-bin.jar /opt/module/sqoop-1.4.6.bin__hadoop-2.0.4-alpha/lib/

3.5 验证安装

3.5.1 查看帮助命令
bash 复制代码
cd /opt/module/sqoop-1.4.6.bin__hadoop-2.0.4-alpha/
bin/sqoop help

预期输出(部分):

复制代码
Available commands:
  codegen            Generate code to interact with database records
  create-hive-table  Import a table definition into Hive
  eval               Evaluate a SQL statement and display the results
  export             Export an HDFS directory to a database table
  help               List available commands
  import             Import a table from a database to HDFS
  import-all-tables  Import tables from a database to HDFS
  import-mainframe   Import datasets from a mainframe server to HDFS
  job                Work with saved jobs
  list-databases     List available databases on a server
  list-tables        List available tables in a database
  merge              Merge results of incremental imports
  metastore          Run a standalone Sqoop metastore
  version            Display version information
3.5.2 测试数据库连接
bash 复制代码
# 测试连接MySQL,列出所有数据库
bin/sqoop list-databases \
--connect jdbc:mysql://hadoop102:3306/ \
--username root \
--password 123456

预期输出

复制代码
information_schema
metastore
mysql
oozie
performance_schema

如果能看到数据库列表,说明Sqoop安装配置成功!🎉


四、数据导入(Import):RDBMS → Hadoop

在Sqoop中,**"导入"**指的是:从非大数据集群(RDBMS)向大数据集群(HDFS、Hive、HBase)中传输数据 ,使用import关键字。

4.1 RDBMS导入到HDFS

4.1.1 准备测试数据

首先在MySQL中创建测试数据库和表:

sql 复制代码
-- 登录MySQL
mysql -uroot -p000000

-- 创建数据库
CREATE DATABASE company;

-- 创建员工表
CREATE TABLE company.staff(
    id INT(4) PRIMARY KEY NOT NULL AUTO_INCREMENT,
    name VARCHAR(255),
    sex VARCHAR(255)
);

-- 插入测试数据
INSERT INTO company.staff(name, sex) VALUES('Thomas', 'Male');
INSERT INTO company.staff(name, sex) VALUES('Catalina', 'FeMale');
INSERT INTO company.staff(name, sex) VALUES('Mike', 'Male');
4.1.2 全部导入

将MySQL表中的全部数据导入到HDFS指定目录:

bash 复制代码
bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--table staff \
--target-dir /user/company \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t"

参数详解

参数 说明
--connect JDBC连接URL
--username / --password 数据库用户名/密码
--table 要导入的表名
--target-dir HDFS目标目录
--delete-target-dir 如果目标目录已存在,先删除(避免报错)
--num-mappers 1 启动1个MapTask(默认4个)
--fields-terminated-by "\t" 字段分隔符为制表符

💡 技巧 :命令中的反斜杠\用于换行,防止Linux直接执行命令。

运行结果验证

bash 复制代码
hdfs dfs -ls /user/company
复制代码
/user/company/_SUCCESS          # MapReduce执行成功标记
/user/company/part-m-00000      # 实际数据文件
bash 复制代码
hdfs dfs -cat /user/company/part-m-00000
复制代码
1	Thomas	Male
2	Catalina	FeMale
3	Mike	Male
4.1.3 查询导入(Query Import)

通过SQL查询语句导入指定条件的数据:

bash 复制代码
bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--target-dir /user/company \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t" \
--query 'SELECT name, sex FROM staff WHERE id <= 2 AND $CONDITIONS;'

⚠️ 重要注意事项

  1. 必须包含$CONDITIONS:这是Sqoop用于数据分片的占位符,保证最终导入数据的顺序和原始数据一致
  2. 使用单引号 :如果SQL语句用双引号,则$CONDITIONS前必须加反斜杠转义(\$CONDITIONS),防止Shell识别为变量
  3. 查询结果不能包含重复字段

错误示例(双引号未转义):

bash 复制代码
--query "SELECT name,sex FROM staff WHERE name = 'mike' AND \$CONDITIONS;"
4.1.4 导入指定列

只导入表中的部分字段:

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

💡 注意--columns中多列用逗号分隔,不要添加空格

运行结果(只有id和sex两列):

复制代码
1	Male
2	FeMale
3	Male
4.1.5 使用WHERE条件筛选导入
bash 复制代码
bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--target-dir /user/company \
--delete-target-dir \
--num-mappers 1 \
--fields-terminated-by "\t" \
--table staff \
--where "id=1"

💡 where可以与columns搭配使用,实现更灵活的数据筛选。


4.2 RDBMS导入到Hive

Sqoop可以直接将MySQL数据导入到Hive表中,无需手动创建Hive表(Sqoop会自动创建)。

bash 复制代码
bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--table staff \
--num-mappers 1 \
--hive-import \
--fields-terminated-by "\t" \
--hive-overwrite \
--hive-table staff_hive

参数详解

参数 说明
--hive-import 将数据导入到Hive
--hive-overwrite 覆盖Hive表中已存在的数据
--hive-table 指定导入到Hive的表名(默认使用MySQL表名)

执行过程解析

复制代码
Step 1: MySQL ──import──▶ HDFS临时目录 (/user/用户名/staff/)
Step 2: HDFS临时目录 ──move──▶ Hive仓库目录 (/user/hive/warehouse/staff_hive/)
Step 3: 删除HDFS临时目录

验证

sql 复制代码
hive> SELECT * FROM staff_hive;

4.3 RDBMS导入到HBase

Sqoop可以直接将MySQL数据导入到HBase中,通过MapReduce直接写入HBase表,不需要中间结果写入HDFS临时目录。

bash 复制代码
bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--table staff \
--columns "id,name,sex" \
--column-family "info" \
--hbase-create-table \
--hbase-row-key "id" \
--hbase-table "hbase_staff" \
--num-mappers 1 \
--split-by id

参数详解

参数 说明
--columns 指定要导入的列
--column-family HBase列族名
--hbase-create-table 自动创建HBase表(Sqoop 1.4.6仅支持HBase 1.0.1之前版本)
--hbase-row-key 指定HBase行键(RowKey)
--hbase-table HBase目标表名
--split-by 指定分片列,提高并行导入效率

⚠️ 版本兼容性注意 :Sqoop 1.4.6只支持HBase 1.0.1之前版本 的自动创建表功能。如果使用更高版本HBase,需要手动创建表

bash 复制代码
hbase shell
hbase> create 'hbase_staff', 'info'
hbase> scan 'hbase_staff'

如果遇到NoSuchMethodError: org.apache.hadoop.hbase.client.HBaseAdmin.<init>报错

建议下载一个低版本的HBase,将其lib目录下的所有jar包复制到Sqoop的lib目录下,遇到重名文件不要替换

运行结果

复制代码
ROW     COLUMN+CELL
 1      column=info:name, timestamp=2023-10-07T17:35:59.519, value=Thomas
 1      column=info:sex, timestamp=2023-10-07T17:35:59.519, value=Male
 2      column=info:name, timestamp=2023-10-07T17:35:59.519, value=Catalina
 2      column=info:sex, timestamp=2023-10-07T17:35:59.519, value=FeMale
 3      column=info:name, timestamp=2023-10-07T17:35:59.519, value=Mike
 3      column=info:sex, timestamp=2023-10-07T17:35:59.519, value=Male
3 row(s)

五、数据导出(Export):Hadoop → RDBMS

在Sqoop中,**"导出"**指的是:从大数据集群(HDFS、Hive、HBase)向非大数据集群(RDBMS)中传输数据 ,使用export关键字。

5.1 Hive/HDFS导出到RDBMS

bash 复制代码
bin/sqoop export \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--table staff \
--num-mappers 1 \
--export-dir /user/hive/warehouse/staff_hive \
--input-fields-terminated-by "\t"

参数详解

参数 说明
--export-dir 要导出的HDFS源目录
--input-fields-terminated-by HDFS数据文件的字段分隔符(必须与导入时一致)
--table MySQL目标表名

⚠️ 重要 :MySQL中如果表不存在,不会自动创建!需要提前在MySQL中创建好目标表。

防止主键冲突

sql 复制代码
-- 清空MySQL表数据
mysql> TRUNCATE TABLE staff;

验证导出结果

sql 复制代码
mysql> SELECT * FROM staff;
复制代码
+----+----------+--------+
| id | name     | sex    |
+----+----------+--------+
|  1 | Thomas   | Male   |
|  2 | Catalina | FeMale |
|  3 | Mike     | Male   |
+----+----------+--------+

⚠️ 如果不加--input-fields-terminated-by参数:整个数据将会被当做一个字符串存到MySQL表中的第一个字段!


六、增量导入(Incremental Import)

在实际生产环境中,数据是持续增长的。全量导入效率太低,Sqoop支持增量导入,只导入新增或修改的数据。

6.1 Append模式(基于自增ID)

适用于:表中有自增主键,只追加新数据

bash 复制代码
bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--table staff \
--num-mappers 1 \
--fields-terminated-by "\t" \
--target-dir /user/hive/warehouse/staff_hive \
--check-column id \
--incremental append \
--last-value 3

参数详解

参数 说明
--check-column 作为增量判断的列名(通常是自增主键)
--incremental append 增量模式:追加
--last-value 上次导入的最大值,只导入大于该值的数据

⚠️ 注意append不能与--hive-*参数同时使用!(Append mode for hive imports is not yet supported

6.2 LastModified模式(基于时间戳)

适用于:表中有更新时间戳字段,导入新增和修改的数据

Step 1:创建带时间戳的表

sql 复制代码
CREATE TABLE company.staff_timestamp(
    id INT(4),
    name VARCHAR(255),
    sex VARCHAR(255),
    last_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

INSERT INTO company.staff_timestamp (id, name, sex) VALUES(1, 'AAA', 'female');
INSERT INTO company.staff_timestamp (id, name, sex) VALUES(2, 'BBB', 'female');

Step 2:首次全量导入

bash 复制代码
bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--table staff_timestamp \
--delete-target-dir \
--m 1

Step 3:MySQL中新增数据

sql 复制代码
INSERT INTO company.staff_timestamp (id, name, sex) VALUES(3, 'CCC', 'female');

Step 4:增量导入

bash 复制代码
bin/sqoop import \
--connect jdbc:mysql://hadoop102:3306/company \
--username root \
--password 000000 \
--table staff_timestamp \
--check-column last_modified \
--incremental lastmodified \
--last-value "2023-09-28 22:20:38" \
--m 1 \
--append

⚠️ 注意

  • 使用lastmodified方式需要指定增量数据是--append(追加)还是--merge-key(合并)
  • --last-value指定的值会包含于增量导入的数据中(即包含边界值)

七、Sqoop脚本打包(Job自动化)

在实际项目中,Sqoop命令通常需要定时执行 (如每天凌晨同步数据)。将命令打包为脚本文件,可以方便地交给Oozie、Azkaban等任务调度框架执行。

7.1 创建opt脚本文件

bash 复制代码
# 创建存放脚本的目录
mkdir -p /opt/module/sqoop-1.4.6.bin__hadoop-2.0.4-alpha/opt/

# 创建脚本文件
vim /opt/module/sqoop-1.4.6.bin__hadoop-2.0.4-alpha/opt/job_HDFS2RDBMS.opt

脚本内容 (每行一个参数,不能有空格):

properties 复制代码
export
--connect
jdbc:mysql://hadoop102:3306/company
--username
root
--password
000000
--table
staff
--num-mappers
1
--export-dir
/user/hive/warehouse/staff_hive
--input-fields-terminated-by
"\t"

7.2 执行脚本

bash 复制代码
bin/sqoop --options-file opt/job_HDFS2RDBMS.opt

执行前清空MySQL表

sql 复制代码
TRUNCATE TABLE staff;

验证结果

sql 复制代码
SELECT * FROM staff;

💡 类似Hive的hql文件 :可以通过hive -f命令执行hql文件中的命令,Sqoop的opt文件同理。


八、Sqoop常用命令与参数速查表

8.1 常用命令一览

序号 命令 说明
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的元数据信息
12 help HelpTool 打印帮助信息
13 version VersionTool 打印版本信息

8.2 公用参数:数据库连接

参数 说明
--connect 连接关系型数据库的URL
--connection-manager 指定要使用的连接管理类
--driver JDBC驱动类
--username 连接数据库的用户名
--password 连接数据库的密码
--verbose 在控制台打印详细信息

8.3 Import特有参数

参数 说明
--append 将数据追加到HDFS已存在的DataSet中
--as-avrodatafile 导入到Avro数据文件
--as-sequencefile 导入到Sequence文件
--as-textfile 导入到普通文本文件(默认)
--columns <col1,col2> 指定要导入的字段
--m / --num-mappers <n> 启动N个Map并行导入(默认4个)
--query / --e <sql> 通过SQL查询导入(必须含$CONDITIONS
--split-by <column> 按指定列分片(不能与--autoreset-to-one-mapper连用)
--table <table> 关系数据库表名
--target-dir <dir> 指定HDFS目标路径
--where <condition> 导入时的WHERE条件
--check-column <col> 增量导入的判断列
--incremental <mode> 增量模式:appendlastmodified
--last-value <value> 增量导入的起始标记值

8.4 Export特有参数

参数 说明
--export-dir <dir> 要导出的HDFS源目录
--update-key <col> 对指定列进行更新操作
--update-mode <mode> updateonly / allowinsert(默认)
--staging-table <table> 创建临时表存放事务结果(防错误)
--clear-staging-table 导出前清空临时表

8.5 Hive相关参数

参数 说明
--hive-import 将数据导入到Hive表
--hive-overwrite 覆盖Hive表中已存在的数据
--create-hive-table 如果目标表已存在则创建失败(默认false)
--hive-table <table> 指定Hive目标表名
--hive-partition-key 创建分区,后跟分区名
--hive-partition-value <v> 导入时指定分区值

九、常见问题与解决方案

9.1 缺少JDBC驱动

报错java.lang.ClassNotFoundException: com.mysql.jdbc.Driver

解决

bash 复制代码
cp mysql-connector-java-*.jar /opt/module/sqoop-1.4.6.bin__hadoop-2.0.4-alpha/lib/

9.2 HBase版本不兼容

报错NoSuchMethodError: org.apache.hadoop.hbase.client.HBaseAdmin.<init>

解决 :下载低版本HBase的lib目录jar包,复制到Sqoop的lib目录(重名文件不要替换)。

9.3 目标目录已存在

报错Target directory already exists

解决 :添加--delete-target-dir参数,或手动删除HDFS目录:

bash 复制代码
hdfs dfs -rm -r /user/company

9.4 导出时主键冲突

报错Duplicate entry '1' for key 'PRIMARY'

解决:导出前清空MySQL表:

sql 复制代码
TRUNCATE TABLE staff;

9.5 分隔符不匹配

现象:导出后MySQL中所有数据挤在一个字段

解决 :确保--fields-terminated-by(导入)和--input-fields-terminated-by(导出)参数一致。


十、完整数据链路总结

在实际的大数据项目中,Sqoop通常处于数据链路的关键位置:


十一、总结

本文从Sqoop的安装配置出发,系统讲解了RDBMS与Hadoop之间的双向数据迁移

方向 场景 核心命令
导入 MySQL → HDFS sqoop import + --target-dir
导入 MySQL → Hive sqoop import + --hive-import
导入 MySQL → HBase sqoop import + --hbase-table
导出 HDFS/Hive → MySQL sqoop export + --export-dir
增量 追加新数据 --incremental append
增量 按时间更新 --incremental lastmodified
自动化 定时任务 .opt脚本 + 调度框架

核心要点回顾

  • ✅ Sqoop将命令翻译为MapReduce程序,高效并行处理
  • ✅ 导入时注意$CONDITIONS占位符和分隔符设置
  • ✅ 导出时确保MySQL表已存在且分隔符匹配
  • ✅ 增量导入支持appendlastmodified两种模式
  • ✅ 使用.opt脚本打包命令,便于任务调度
相关推荐
光电的一只菜鸡2 天前
小白从零开始学agent(二)——如何高效编写 Prompt 与 Skill
hadoop·microsoft·prompt
William Dawson5 天前
【踩坑实录|Hive1\.2\.1数据服务接口5大疑难问题调试与全方位优化方案】
java·hive·spring boot
ha_lydms5 天前
Hologres 简介
大数据·hadoop·阿里云·mapreduce·yarn·dataworks·hologres
Francek Chen8 天前
【大数据处理与分析】实验5:MapReduce初级编程实践
大数据·hadoop·分布式·mapreduce
牛奶咖啡1312 天前
大数据Hadoop运维应用实践——HIVE与Hadoop实现整合_Hive的配置安装与使用
大数据·hive·hive的配置与安装·metastore服务的配置·hiveserver2服务配置·hive的常用sql操作·beeline的使用
Zhu75813 天前
在k8s集群环境部署高可用的Apache Hadoop3.1.1定制版集群
hadoop·kubernetes
还有你Y14 天前
软件工程架构
hadoop·架构·软件工程
向夏威夷 梦断明暄14 天前
基于Tez引擎的 Hive SQL 性能优化
hive·sql·性能优化
曾阿伦18 天前
Windows 下运行 Hadoop 并部署到 AWS EMR 指南
hadoop·windows·aws
极光代码工作室19 天前
基于Spark的日志监控与分析平台
大数据·hadoop·python·spark·数据可视化