sqoop简介

Sqoop:Hadoop 和 MySQL 之间的”数据搬运工”

Sqoop 就干一件事:Hadoop 和关系型数据库之间搬数据。

  • 导入(Import):MySQL/PostgreSQL → HDFS/Hive/HBase
  • 导出(Export):HDFS/Hive → MySQL/PostgreSQL

业务数据在 MySQL 里,要拉到 Hive 做离线分析 → 用 Sqoop Import。
分析结果在 HDFS 上,要推回 MySQL 供业务系统用 → 用 Sqoop Export。

数据导入(Import):从 MySQL 到 HDFS

最常用的操作——把业务数据库的表导入 HDFS。

1. 全量导入:整张表一次性拉过来

sqoop import \
  --connect jdbc:mysql://localhost:3306/testdb \
  --username root \
  --password 123456 \
  --table user_info \
  --target-dir /user/hadoop/user_info \
  --m 4
参数 说明
--connect 数据库连接地址
--username / --password 数据库账号密码
--table 要导入的表名
--target-dir HDFS 目标目录
-m 4 用 4 个 Map 任务并行

2. 增量导入:只导新增或变化的数据

全量导入只适合第一次,后续需要增量同步。

方式一:按递增列(Append 模式)

sqoop import \
  --connect jdbc:mysql://localhost:3306/testdb \
  --username root \
  --password 123456 \
  --table user_info \
  --target-dir /user/hadoop/user_info \
  --incremental append \
  --check-column id \
  --last-value 1000

只导入 id > 1000 的数据,适合自增 ID 的场景。

方式二:按时间戳(LastModified 模式)

sqoop import \
  --connect jdbc:mysql://localhost:3306/testdb \
  --username root \
  --password 123456 \
  --table orders \
  --target-dir /user/hadoop/orders \
  --incremental lastmodified \
  --check-column update_time \
  --last-value "2024-01-01 00:00:00"

只导入 update_time > 2024-01-01 的数据,适合有更新时间字段的场景。

数据导出(Export):从 HDFS 到 MySQL

把 HDFS 上的分析结果写回关系型数据库,供业务系统查询。

sqoop export \
  --connect jdbc:mysql://localhost:3306/testdb \
  --username root \
  --password 123456 \
  --table user_result \
  --export-dir /user/hadoop/user_result \
  --input-fields-terminated-by ','
参数 说明
--export-dir HDFS 数据目录
--table MySQL 目标表(必须提前创建)
--input-fields-terminated-by 输入文件的分隔符

注意:导出的数据格式必须跟 MySQL 表结构匹配,列数、顺序、类型都对得上。

直接入 Hive:省掉中间步骤

Sqoop 可以直接把数据导入 Hive 表,不用先到 HDFS 再建 Hive 表。

sqoop import \
  --connect jdbc:mysql://localhost:3306/testdb \
  --username root \
  --password 123456 \
  --table user_info \
  --hive-import \
  --hive-table user_info_hive \
  --hive-database default
  • 自动创建 Hive 表(如果不存在)
  • 数据直接进 Hive,不用手动 CREATE TABLE + LOAD DATA

工作机制:Sqoop 底层跑的是 MapReduce

Sqoop 的导入导出,底层是 MapReduce 作业——只用 Map 阶段,没有 Reduce。

Import 流程:
1. 解析命令,连接数据库,获取表结构
2. 生成 POJO 类(Java 代码)
3. 启动 Map 任务,并行读取数据库数据
4. 写入 HDFS(CSV / SequenceFile / Parquet)

Export 流程:
1. 解析命令,连接数据库
2. 启动 Map 任务,并行读取 HDFS 数据
3. 通过 JDBC 批量写入 MySQL

并行度控制: -m 4 控制同时多少个 Map 任务从数据库拉数据。

注意: 并行度太高会给数据库造成压力,需要平衡性能和数据库负载。

实用特性

1. 压缩存储

导入时指定压缩,节省 HDFS 空间:

sqoop import \
  --table user_info \
  --target-dir /user/hadoop/user_info \
  --compress \
  --compression-codec org.apache.hadoop.io.compress.GzipCodec

2. 过滤部分数据

只导满足条件的行:

sqoop import \
  --table orders \
  --where "status = 'completed' AND amount > 1000"

3. 只导部分列

sqoop import \
  --table user_info \
  --columns "id,name,email"

4. 类型映射

数据库和 HDFS 类型有差异时,手动指定:

--map-column-java "age=Integer,created_at=String"

常见问题

1. 导数据时数据库连接被撑爆

Map 并行度太高,数据库连接数不够。

解决: 降低 -m 的值,或者调大数据库连接池。

2. 增量导入重复数据

--last-value 没设对,或者时间精度不够。

解决: 确认 --check-column 字段准确,--last-value 用上次导入的最大值。

3. 导出时 MySQL 表要有主键

Sqoop 导出依赖主键来做更新和冲突处理。如果表没有主键,用 --update-mode allowinsert 可能会报错。

4. 数据格式不匹配

HDFS 文件的分隔符、字段数跟 MySQL 表结构对不上。

解决: 检查 --input-fields-terminated-by 是否匹配,字段顺序是否一致。