本文是大数据系列第 22 篇,演示使用 Sqoop 将 MySQL 表数据全量导入 HDFS 的完整操作流程。

完整图文版(含截图):CSDN 原文 | 掘金

实验环境

三台 2C4G 公有云服务器(h121、h122、h123)组成 Hadoop 集群,其中 h122 承担 MySQL 服务。HDFS、YARN 和 Hive 服务均已就绪。

准备测试数据

在 MySQL 中创建测试表并批量插入数据:

CREATE DATABASE sqoop;
USE sqoop;

CREATE TABLE goodtbl (
  gname        VARCHAR(50),
  serialNumber INT,
  price        INT,
  stock_number INT,
  create_time  DATE
);

-- 使用存储过程批量插入 100 条测试记录
CALL batchInsertTestData(1, 100);

全量导入命令

sqoop import \
  --connect jdbc:mysql://h122.wzk.icu:3306/sqoop \
  --username hive \
  --password hive@wzk.icu \
  --table goodtbl \
  --target-dir /user/hadoop/goodtbl \
  --delete-target-dir \
  --num-mappers 4 \
  --fields-terminated-by "\t"

关键参数说明

参数说明
--connectJDBC 连接字符串
--username / --password数据库凭证
--table源表名
--target-dirHDFS 目标目录
--delete-target-dir若目标目录已存在则先删除,避免冲突
--num-mappers并行 Mapper 数量(默认 4)
--fields-terminated-by输出字段分隔符

MapReduce 并行机制

Sqoop 导入时自动生成 MapReduce Job,多个 Mapper 并行工作:

  1. 读取源表主键范围(min / max)
  2. 将范围均匀切分为 N 个区间(N = --num-mappers
  3. 每个 Mapper 通过 JDBC 拉取对应区间的数据分片
  4. 各 Mapper 输出文件写入 HDFS 目标目录

例如主键 1-100、4 个 Mapper 时,分片为:1-25、26-50、51-75、76-100。

若表无主键或主键分布不均,可用 --split-by 指定分割列:

sqoop import \
  --connect jdbc:mysql://h122.wzk.icu:3306/sqoop \
  --username hive \
  --password hive@wzk.icu \
  --table goodtbl \
  --target-dir /user/hadoop/goodtbl \
  --split-by serialNumber \
  --num-mappers 4 \
  --fields-terminated-by "\t"

自定义查询导入

当需要多表 JOIN 或复杂过滤时,使用 --query 替代 --table

sqoop import \
  --connect jdbc:mysql://h122.wzk.icu:3306/sqoop \
  --username hive \
  --password hive@wzk.icu \
  --query "SELECT gname, price, create_time FROM goodtbl WHERE \$CONDITIONS" \
  --target-dir /user/hadoop/goodtbl_filtered \
  --split-by serialNumber \
  --num-mappers 2 \
  --fields-terminated-by "\t"

注意:使用 --query 时,WHERE 子句必须包含 $CONDITIONS 占位符(双引号中需转义为 \$CONDITIONS),Sqoop 会自动替换为分片条件。

验证导入结果

# 查看 HDFS 上生成的文件
hdfs dfs -ls /user/hadoop/goodtbl

# 查看数据内容(前 5 行)
hdfs dfs -cat /user/hadoop/goodtbl/part-m-00000 | head -5

典型输出(制表符分隔):

商品A    1    88    100    2024-01-01
商品B    2    66    200    2024-01-02

常见问题

Q:导入报错 Target directory already exists A:添加 --delete-target-dir 参数,或提前执行 hdfs dfs -rm -r /target/path

Q:Mapper 数量设为 1 还是多个? A:小表用 -m 1 避免不必要的并行开销;大表根据集群资源适当提高,通常 4-8 个 Mapper 效果较好。

Q:密码明文有安全风险怎么办? A:可使用 --password-file 参数指定包含密码的 HDFS 文件,避免明文暴露在命令历史中。


下一篇介绍 Sqoop 部分导入:通过 --query--columns--where 三种方式实现条件过滤导入。