搜 索

Sqoop 快速了解 & 为什么被淘汰

  • 19阅读
  • 2023年02月11日
  • 0评论
首页 / AI/大数据 / 正文

前言:一个关于"搬砖"的故事

在大数据的世界里,有一个永恒的问题:

"MySQL里有10亿条数据,怎么弄到Hadoop里?"

如果你是个愣头青,可能会说:"写个Python脚本,一条一条读出来,再一条一条写进去呗!"

然后你就会发现——跑了三天三夜,进度条还在1%。

如果你稍微有点经验,可能会说:"用JDBC批量读取,多线程并行写入!"

然后你就会发现——MySQL被你的并发查询搞崩了,DBA提着刀来找你。

这时候,一个叫Sqoop的工具出现了。它的名字来源于SQL-to-Hadoop,使命就是在关系型数据库和Hadoop之间搬砖

今天,让我们快速了解这个曾经的"数据搬运之王",以及它为什么正在被时代淘汰。


一、Sqoop是什么?

1.1 一句话定义

Sqoop = SQL to Hadoop,是Apache旗下的一个工具,用于在关系型数据库(MySQL、Oracle、PostgreSQL等)和Hadoop生态(HDFS、Hive、HBase)之间高效传输数据。

graph LR subgraph 关系型数据库["🗄️ 关系型数据库"] MySQL[(MySQL)] Oracle[(Oracle)] PG[(PostgreSQL)] SQLServer[(SQL Server)] end subgraph Sqoop["🔄 Sqoop"] Import[Import
导入到Hadoop] Export[Export
导出到数据库] end subgraph Hadoop生态["🐘 Hadoop生态"] HDFS[HDFS] Hive[Hive] HBase[HBase] end MySQL --> Import Oracle --> Import PG --> Import SQLServer --> Import Import --> HDFS Import --> Hive Import --> HBase HDFS --> Export Hive --> Export Export --> MySQL Export --> Oracle style Sqoop fill:#4ecdc4

1.2 Sqoop的两大核心功能

功能方向说明
Import数据库 → Hadoop把MySQL等数据库的数据导入到HDFS/Hive/HBase
ExportHadoop → 数据库把HDFS/Hive的数据导出到MySQL等数据库

简单来说,Sqoop就是个数据搬运工

  • Import = 从数据库搬到Hadoop
  • Export = 从Hadoop搬回数据库

1.3 Sqoop的版本

timeline title Sqoop版本演进 2009 : Sqoop 1.0诞生 : Cloudera开发 : 基于MapReduce 2012 : Sqoop成为Apache顶级项目 : 广泛使用 2012 : Sqoop2开始开发 : 引入Server架构 : 想解决Sqoop1的问题 2014-2017 : Sqoop2持续开发 : 但一直不稳定 : 社区吐槽不断 2018 : Apache宣布Sqoop2退役 : 回归Sqoop1 : 但Sqoop1也停止大更新 2021 : Apache宣布Sqoop整体退役 : 进入Attic(Apache养老院) : 正式被时代淘汰
🪦 讣告:Apache Sqoop于2021年正式退役,进入Apache Attic。这意味着官方不再维护,虽然你还能用,但出了问题没人管了。

二、Sqoop的工作原理

2.1 核心原理:把导入导出变成MapReduce任务

Sqoop的核心思想很简单:把数据传输任务转换成MapReduce任务,利用Hadoop集群的并行能力来加速数据传输。

graph TB subgraph Sqoop工作原理["⚙️ Sqoop Import原理"] subgraph 准备阶段["1️⃣ 准备阶段"] A[连接数据库] --> B[读取表元数据] B --> C[生成Java类
用于序列化] C --> D[计算数据分片] end subgraph 执行阶段["2️⃣ 执行阶段(MapReduce)"] D --> M1[Mapper1
SELECT ... WHERE id BETWEEN 1 AND 1000000] D --> M2[Mapper2
SELECT ... WHERE id BETWEEN 1000001 AND 2000000] D --> M3[Mapper3
SELECT ... WHERE id BETWEEN 2000001 AND 3000000] D --> M4[Mapper4
SELECT ... WHERE id BETWEEN 3000001 AND 4000000] end subgraph 输出阶段["3️⃣ 输出阶段"] M1 --> O1[part-m-00000] M2 --> O2[part-m-00001] M3 --> O3[part-m-00002] M4 --> O4[part-m-00003] end end style M1 fill:#ff6b6b style M2 fill:#ff6b6b style M3 fill:#ff6b6b style M4 fill:#ff6b6b

关键点

  1. Sqoop根据--split-by指定的列(通常是主键)来分片
  2. 每个Mapper负责一个数据范围的查询
  3. 默认4个Mapper并行执行
  4. 没有Reducer,Mapper直接输出到HDFS

2.2 数据分片策略

graph TB subgraph 分片计算["📊 数据分片计算"] A["假设:表有1000万条数据
主键id范围:1 ~ 10000000
Mapper数量:4"] A --> B["计算边界:
SELECT MIN(id), MAX(id) FROM table"] B --> C["计算步长:
(10000000 - 1) / 4 = 2500000"] C --> D1["Mapper1: id >= 1 AND id < 2500001"] C --> D2["Mapper2: id >= 2500001 AND id < 5000001"] C --> D3["Mapper3: id >= 5000001 AND id < 7500001"] C --> D4["Mapper4: id >= 7500001 AND id <= 10000000"] end style A fill:#ffe66d

⚠️ 分片的坑

  • 如果split-by列分布不均匀,会导致数据倾斜
  • 如果split-by列有大量NULL值,可能丢数据
  • 如果split-by列不是数字类型,需要特殊处理

三、Sqoop实战命令

3.1 Import:从数据库导入到Hadoop

基础导入到HDFS

sqoop import \
  --connect jdbc:mysql://localhost:3306/mydb \
  --username root \
  --password 123456 \
  --table user_info \
  --target-dir /user/hive/warehouse/user_info \
  --delete-target-dir \
  --num-mappers 4 \
  --split-by id

导入到Hive表

sqoop import \
  --connect jdbc:mysql://localhost:3306/mydb \
  --username root \
  --password 123456 \
  --table user_info \
  --hive-import \
  --hive-database mydb \
  --hive-table user_info \
  --hive-overwrite \
  --num-mappers 4 \
  --split-by id

增量导入(Append模式)

sqoop import \
  --connect jdbc:mysql://localhost:3306/mydb \
  --username root \
  --password 123456 \
  --table orders \
  --target-dir /user/hive/warehouse/orders \
  --incremental append \
  --check-column id \
  --last-value 1000000 \
  --num-mappers 4

增量导入(LastModified模式)

sqoop import \
  --connect jdbc:mysql://localhost:3306/mydb \
  --username root \
  --password 123456 \
  --table orders \
  --target-dir /user/hive/warehouse/orders \
  --incremental lastmodified \
  --check-column update_time \
  --last-value "2024-01-01 00:00:00" \
  --num-mappers 4 \
  --merge-key id

3.2 Export:从Hadoop导出到数据库

sqoop export \
  --connect jdbc:mysql://localhost:3306/mydb \
  --username root \
  --password 123456 \
  --table user_result \
  --export-dir /user/hive/warehouse/user_result \
  --input-fields-terminated-by '\001' \
  --num-mappers 4 \
  --update-key id \
  --update-mode allowinsert

3.3 常用参数速查表

mindmap root((Sqoop常用参数)) 连接参数 --connect JDBC连接串 --username 用户名 --password 密码 --password-file 密码文件,更安全 导入参数 --table 表名 --columns 指定列 --where 过滤条件 --query 自定义SQL --target-dir HDFS目标路径 --num-mappers 并行度 --split-by 分片列 Hive参数 --hive-import 导入到Hive --hive-database Hive库名 --hive-table Hive表名 --hive-overwrite 覆盖写入 增量参数 --incremental append或lastmodified --check-column 检查列 --last-value 上次值 格式参数 --as-textfile 文本格式 --as-parquetfile Parquet格式 --as-avrodatafile Avro格式

四、Sqoop的合并与压缩

这是Sqoop使用中非常重要但经常被忽略的话题。

4.1 小文件问题(又是它!)

Sqoop默认每个Mapper输出一个文件,如果你设置了4个Mapper,就会产生4个文件。看起来没问题对吧?

但是,考虑这个场景:

graph TB subgraph 增量导入灾难["😱 增量导入的小文件灾难"] A["每天增量导入一次
4个Mapper = 4个文件"] A --> B["一年后:
365 × 4 = 1460个文件"] B --> C["如果是100张表:
1460 × 100 = 14.6万个文件"] C --> D["而且每个文件可能只有几MB"] D --> E["NameNode:我裂开了 💀"] end style E fill:#ff0000,color:#fff

4.2 解决方案一:减少Mapper数量

# 如果数据量不大,用1个Mapper
sqoop import \
  --connect jdbc:mysql://localhost:3306/mydb \
  --username root \
  --password 123456 \
  --table small_table \
  --target-dir /user/hive/warehouse/small_table \
  --num-mappers 1  # 只用1个Mapper

问题:数据量大时,单Mapper太慢。

4.3 解决方案二:使用压缩

压缩不仅能减少存储空间,还能减少网络传输,提升性能。

# 使用Snappy压缩(推荐,压缩/解压快)
sqoop import \
  --connect jdbc:mysql://localhost:3306/mydb \
  --username root \
  --password 123456 \
  --table user_info \
  --target-dir /user/hive/warehouse/user_info \
  --compress \
  --compression-codec org.apache.hadoop.io.compress.SnappyCodec \
  --num-mappers 4

# 使用Gzip压缩(压缩比高,但解压慢)
sqoop import \
  ... \
  --compress \
  --compression-codec org.apache.hadoop.io.compress.GzipCodec

# 使用LZO压缩(可分片,适合大文件)
sqoop import \
  ... \
  --compress \
  --compression-codec com.hadoop.compression.lzo.LzopCodec

压缩格式对比

压缩格式压缩比压缩速度解压速度是否可分片推荐场景
Snappy实时性要求高
LZO是(需索引)大文件
Gzip冷数据归档
Bzip2最高最慢最慢极致压缩

4.4 解决方案三:使用Parquet/ORC格式

这是最推荐的方案,直接导入为列式存储格式。

# 导入为Parquet格式
sqoop import \
  --connect jdbc:mysql://localhost:3306/mydb \
  --username root \
  --password 123456 \
  --table user_info \
  --target-dir /user/hive/warehouse/user_info \
  --as-parquetfile \
  --parquet-configurator-implementation org.apache.sqoop.parquet.hadoop.HadoopParquetImportConfigurator \
  --num-mappers 4

# Parquet自带压缩,也可以指定
sqoop import \
  ... \
  --as-parquetfile \
  --compress \
  --compression-codec snappy

4.5 解决方案四:后置合并

如果Sqoop导入产生了小文件,可以在导入后手动合并。

flowchart TB subgraph 后置合并方案["🔧 后置合并方案"] A[Sqoop导入完成
产生多个小文件] --> B{选择合并方式} B --> C1["方案1: Hive CONCATENATE
仅ORC格式"] B --> C2["方案2: INSERT OVERWRITE
通用但慢"] B --> C3["方案3: Hadoop命令合并
getmerge"] B --> C4["方案4: Spark合并
灵活高效"] C1 --> D["ALTER TABLE t CONCATENATE"] C2 --> D2["INSERT OVERWRITE TABLE t
SELECT * FROM t"] C3 --> D3["hdfs dfs -getmerge
本地合并后上传"] C4 --> D4["df.coalesce(1).write..."] end style C1 fill:#4ecdc4 style C4 fill:#4ecdc4

Hive CONCATENATE示例

-- 仅适用于ORC格式的表
ALTER TABLE user_info PARTITION(dt='2024-01-01') CONCATENATE;

Spark合并示例

# 读取Sqoop导入的数据
df = spark.read.parquet("/user/hive/warehouse/user_info")

# 合并后重新写入
df.coalesce(1).write.mode("overwrite").parquet("/user/hive/warehouse/user_info_merged")

4.6 解决方案五:导入到Hive时自动合并

# Sqoop导入到Hive时,设置Hive的合并参数
sqoop import \
  --connect jdbc:mysql://localhost:3306/mydb \
  --username root \
  --password 123456 \
  --table user_info \
  --hive-import \
  --hive-database mydb \
  --hive-table user_info \
  --num-mappers 4 \
  -- --hive.merge.mapfiles=true \
  -- --hive.merge.mapredfiles=true \
  -- --hive.merge.size.per.task=256000000

4.7 最佳实践:完整的Sqoop导入脚本

#!/bin/bash
# Sqoop导入最佳实践脚本

# 变量定义
DB_HOST="mysql.example.com"
DB_PORT="3306"
DB_NAME="mydb"
DB_USER="sqoop_user"
DB_PWD_FILE="/etc/sqoop/mysql.pwd"
TABLE_NAME="user_info"
HIVE_DB="dw"
HIVE_TABLE="ods_user_info"
DT=$(date +%Y-%m-%d)
NUM_MAPPERS=4

# 导入命令
sqoop import \
  --connect "jdbc:mysql://${DB_HOST}:${DB_PORT}/${DB_NAME}?useSSL=false&characterEncoding=UTF-8" \
  --username ${DB_USER} \
  --password-file ${DB_PWD_FILE} \
  --table ${TABLE_NAME} \
  --hive-import \
  --hive-database ${HIVE_DB} \
  --hive-table ${HIVE_TABLE} \
  --hive-partition-key dt \
  --hive-partition-value ${DT} \
  --hive-overwrite \
  --as-parquetfile \
  --compress \
  --compression-codec snappy \
  --num-mappers ${NUM_MAPPERS} \
  --split-by id \
  --null-string '\\N' \
  --null-non-string '\\N' \
  --fetch-size 10000

# 检查执行结果
if [ $? -eq 0 ]; then
    echo "✅ Sqoop导入成功: ${TABLE_NAME} -> ${HIVE_DB}.${HIVE_TABLE}, 分区: dt=${DT}"
    
    # 合并小文件(如果是ORC格式)
    # hive -e "ALTER TABLE ${HIVE_DB}.${HIVE_TABLE} PARTITION(dt='${DT}') CONCATENATE;"
    
else
    echo "❌ Sqoop导入失败!"
    exit 1
fi

五、Sqoop的痛点与局限

说了这么多,现在让我们来吐槽一下Sqoop的问题。

5.1 Sqoop的七宗罪

graph TB subgraph Sqoop的问题["😤 Sqoop的七宗罪"] P1["1. 依赖MapReduce
启动慢,小数据杀鸡用牛刀"] P2["2. 不支持实时同步
只能批量,无法CDC"] P3["3. 配置复杂
参数多,容易出错"] P4["4. 数据库压力大
全量查询可能拖垮数据库"] P5["5. 类型映射问题
数据库类型和Hive类型不完全兼容"] P6["6. 小文件问题
多Mapper产生多个小文件"] P7["7. 已停止维护
官方已退役,有Bug没人修"] end style P1 fill:#ff6b6b style P2 fill:#ff6b6b style P7 fill:#ff0000,color:#fff

5.2 详细分析

问题1:依赖MapReduce,启动开销大

sequenceDiagram participant User as 用户 participant Sqoop as Sqoop participant YARN as YARN participant MR as MapReduce participant MySQL as MySQL participant HDFS as HDFS User->>Sqoop: 执行sqoop import Note over Sqoop: 解析参数,生成代码 Sqoop->>YARN: 提交MR任务 Note over YARN: 等待资源分配... Note over YARN: 可能要等几十秒 YARN->>MR: 启动Container Note over MR: 初始化Mapper... MR->>MySQL: 开始查询 MySQL->>HDFS: 数据传输 Note over HDFS: 写入完成 MR->>User: 任务完成 Note over User,HDFS: 如果只有1MB数据
启动开销可能比传输时间还长!

真实场景:导入1MB数据,启动MR花了2分钟,实际传输只要3秒。

问题2:不支持实时/CDC

graph LR subgraph Sqoop能做的["✅ Sqoop能做的"] A1[全量导入] --> B1[每次全量覆盖] A2[增量导入] --> B2[基于时间戳/自增ID
只能追加,不能更新] end subgraph Sqoop不能做的["❌ Sqoop不能做的"] C1[实时同步] --> D1[无法做到秒级同步] C2[CDC变更捕获] --> D2[无法捕获UPDATE/DELETE] C3[Binlog解析] --> D3[不支持] end style C1 fill:#ff6b6b style C2 fill:#ff6b6b style C3 fill:#ff6b6b

问题3:对源数据库压力大

graph TB subgraph 数据库压力["💀 Sqoop对数据库的压力"] A[Sqoop启动4个Mapper] --> B[4个并发的大范围查询] B --> C["SELECT * FROM table
WHERE id BETWEEN x AND y"] C --> D[数据库资源被占用] D --> E["其他业务查询变慢
甚至超时"] E --> F["DBA提着刀来找你 🔪"] end style F fill:#ff0000,color:#fff

六、为什么Sqoop被淘汰?

6.1 时代变了

timeline title 数据集成技术演进 2009-2015 : Sqoop时代 : 批量ETL为主 : T+1数据延迟可接受 : MapReduce是主流 2015-2018 : 过渡期 : 实时需求增加 : Spark崛起 : Kafka普及 2018-2020 : CDC时代来临 : Flink CDC出现 : Debezium成熟 : 实时数仓兴起 2020-现在 : Sqoop退役 : DataX/SeaTunnel替代批量场景 : Flink CDC替代实时场景 : Sqoop成为历史

6.2 替代方案对比

graph TB subgraph 替代方案["🚀 Sqoop的替代方案"] subgraph 批量场景["批量ETL场景"] DataX[DataX
阿里开源] SeaTunnel[SeaTunnel
原Waterdrop] Spark[Spark JDBC] end subgraph 实时场景["实时CDC场景"] FlinkCDC[Flink CDC
实时同步神器] Debezium[Debezium
CDC框架] Canal[Canal
阿里开源] Maxwell[Maxwell
Binlog解析] end subgraph 云原生["云原生场景"] DMS[云厂商DMS
AWS/阿里云/腾讯云] Fivetran[Fivetran
SaaS数据集成] Airbyte[Airbyte
开源数据集成] end end style FlinkCDC fill:#4ecdc4 style DataX fill:#4ecdc4 style SeaTunnel fill:#4ecdc4

6.3 详细对比表

特性SqoopDataXFlink CDCCanal
同步模式批量批量实时实时
架构依赖MR/YARN单机/分布式Flink集群独立服务
CDC支持
启动开销
配置复杂度
数据库压力小(Binlog)小(Binlog)
维护状态已退役活跃活跃活跃
学习成本

6.4 替代方案介绍

DataX:阿里开源的数据同步工具

graph TB subgraph DataX架构["📦 DataX架构"] subgraph Reader["Reader插件"] R1[MySQLReader] R2[OracleReader] R3[HDFSReader] R4[...] end subgraph Framework["DataX Framework"] F1[调度] F2[缓存] F3[限流] end subgraph Writer["Writer插件"] W1[HDFSWriter] W2[HiveWriter] W3[MySQLWriter] W4[...] end Reader --> Framework --> Writer end

DataX优势

  • 插件化架构,支持多种数据源
  • 单机运行,启动快
  • 配置简单,JSON格式
  • 阿里大规模使用验证

DataX配置示例

{
  "job": {
    "content": [{
      "reader": {
        "name": "mysqlreader",
        "parameter": {
          "connection": [{
            "jdbcUrl": ["jdbc:mysql://localhost:3306/mydb"],
            "table": ["user_info"]
          }],
          "username": "root",
          "password": "123456",
          "column": ["id", "name", "age"]
        }
      },
      "writer": {
        "name": "hdfswriter",
        "parameter": {
          "path": "/user/hive/warehouse/user_info",
          "fileName": "user_info",
          "column": [
            {"name": "id", "type": "bigint"},
            {"name": "name", "type": "string"},
            {"name": "age", "type": "int"}
          ],
          "fileType": "parquet",
          "compress": "snappy"
        }
      }
    }],
    "setting": {
      "speed": {"channel": 4}
    }
  }
}

Flink CDC:实时数据同步神器

graph LR subgraph FlinkCDC["⚡ Flink CDC架构"] MySQL[(MySQL)] --> |"Binlog"|Debezium[Debezium
Connector] Debezium --> Flink[Flink
实时处理] Flink --> |"实时写入"|Targets[HDFS/Hive/Kafka/...] end subgraph 特点["💡 特点"] T1[秒级延迟] T2[支持INSERT/UPDATE/DELETE] T3[不影响源数据库性能] T4[Exactly-Once语义] end style Flink fill:#ff6b6b

Flink CDC示例

-- 创建CDC源表
CREATE TABLE mysql_users (
    id BIGINT,
    name STRING,
    age INT,
    update_time TIMESTAMP(3),
    PRIMARY KEY (id) NOT ENFORCED
) WITH (
    'connector' = 'mysql-cdc',
    'hostname' = 'localhost',
    'port' = '3306',
    'username' = 'root',
    'password' = '123456',
    'database-name' = 'mydb',
    'table-name' = 'user_info'
);

-- 创建目标表
CREATE TABLE hive_users (
    id BIGINT,
    name STRING,
    age INT,
    update_time TIMESTAMP(3)
) WITH (
    'connector' = 'hive',
    ...
);

-- 实时同步
INSERT INTO hive_users SELECT * FROM mysql_users;

七、迁移指南:从Sqoop到新方案

7.1 迁移决策树

flowchart TB Start[准备迁移Sqoop] --> Q1{数据同步需求?} Q1 --> |"批量/T+1"|Q2{数据量级?} Q1 --> |"实时/CDC"|Q3{技术栈?} Q2 --> |"小于10GB/天"|DataX["推荐: DataX
简单高效"] Q2 --> |"大于10GB/天"|Q4{有Spark集群?} Q4 --> |"有"|SparkJDBC["推荐: Spark JDBC
利用现有资源"] Q4 --> |"没有"|SeaTunnel["推荐: SeaTunnel
分布式能力"] Q3 --> |"有Flink"|FlinkCDC["推荐: Flink CDC
最强CDC方案"] Q3 --> |"无Flink"|Q5{只需MySQL?} Q5 --> |"是"|Canal["推荐: Canal
轻量级"] Q5 --> |"否"|Debezium["推荐: Debezium
多数据源"] style DataX fill:#4ecdc4 style FlinkCDC fill:#4ecdc4 style SparkJDBC fill:#4ecdc4

7.2 Sqoop命令迁移对照表

Sqoop命令DataX配置Flink CDC SQL
--connectjdbcUrl'hostname', 'port'
--tabletable'table-name'
--columnscolumnSELECT指定列
--wherewhereWHERE子句
--num-mapperschannel并行度配置
--split-bysplitPk自动处理
--as-parquetfilefileType: parquetSink配置

八、总结

8.1 Sqoop的历史地位

graph TB subgraph Sqoop的贡献["🏆 Sqoop的历史贡献"] A[开创了数据库到Hadoop的桥梁] B[推动了数据仓库向Hadoop迁移] C[成为大数据ETL的标准工具] D[培养了一代大数据工程师] end subgraph Sqoop的结局["📜 Sqoop的结局"] E[2021年正式退役] F[进入Apache Attic] G[被更先进的工具取代] H[但其思想仍在延续] end style A fill:#ffe66d style E fill:#95a5a6

8.2 一句话总结

Sqoop是大数据时代的开拓者,它完成了历史使命,现在是时候说再见了。

如果你是新项目,不要再用Sqoop了,直接上DataX或Flink CDC。

如果你有历史项目在用Sqoop,建议尽快规划迁移,因为:

  1. 官方不再维护,安全漏洞没人修
  2. 新版本Hadoop/Hive可能兼容性问题
  3. 更好的工具已经成熟

8.3 技术选型建议

mindmap root((数据同步技术选型)) 批量同步 小数据量 DataX 简单脚本 大数据量 SeaTunnel Spark JDBC 实时同步 MySQL Canal Flink CDC 多数据源 Debezium Flink CDC 云上场景 用云厂商DMS 省心省力

九、写在最后

写这篇文章的时候,我有点感慨。

Sqoop是我入门大数据时学的第一个工具。当年为了搞懂它的参数,我把官方文档翻了不下十遍,踩了无数的坑:

  • 忘记加--null-string,导入的NULL变成了字符串"null"
  • split-by选了个分布不均匀的列,一个Mapper跑了2小时,其他3个1分钟就完事
  • 导出时主键冲突,整个任务失败从头来
  • ......

但正是这些坑,让我真正理解了数据同步的复杂性。

技术在进步,工具在迭代,Sqoop退役了,但它教会我们的东西不会过时:

数据同步的核心挑战永远是:如何在保证数据一致性的前提下,高效、稳定地把数据从A搬到B。

不管是Sqoop、DataX还是Flink CDC,解决的都是这个问题。

好了,Sqoop,再见了老伙计!👋


本文作者:一个曾经和Sqoop相爱相杀的程序员

最惨经历:Sqoop导出时忘记设update-mode,把线上表的数据全删了

铭记历史,面向未来!🐘


附录:Sqoop常见问题与面试题

常见问题

Q1: Sqoop导入时报"No primary key could be found"怎么办?

表没有主键时,Sqoop无法自动分片。解决方案:

  1. 使用--split-by指定一个合适的列
  2. 或使用-m 1单Mapper运行

Q2: Sqoop导入中文乱码怎么办?

在连接串中添加字符集参数:
jdbc:mysql://host:3306/db?useUnicode=true&characterEncoding=UTF-8

Q3: Sqoop导入NULL值变成"null"字符串怎么办?

添加参数:
--null-string '\\N' --null-non-string '\\N'

面试题

  1. Sqoop的工作原理是什么?

    Sqoop将数据导入/导出任务转换为MapReduce任务,利用Hadoop集群的并行能力进行数据传输。每个Mapper负责一个数据分片的读取/写入。
  2. Sqoop如何实现增量导入?

    两种模式:

    • Append:基于自增列,只导入新增数据
    • LastModified:基于时间戳列,导入新增和修改的数据
  3. Sqoop的split-by有什么要求?

    split-by列应该:数值型、分布均匀、有索引。如果不满足这些条件,可能导致数据倾斜或性能问题。
  4. 为什么Sqoop被淘汰了?

    依赖MapReduce启动慢、不支持CDC实时同步、对源数据库压力大、已停止维护。被DataX(批量)和Flink CDC(实时)等新工具取代。
  5. 从Sqoop迁移到新方案,你会怎么选择?

    批量场景选DataX/SeaTunnel,实时场景选Flink CDC/Canal,根据数据量和技术栈综合考虑。
无标签
评论区
暂无评论
avatar