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 是否匹配,字段顺序是否一致。