Sqoop 参数

Sqoop 导入数据到 HDFS 中的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/opt/module/sqoop/bin/sqoop import \
--connect jdbc 的 url 字符串\
--username 账号\
--password 密码\
# HDFS 目标的目录
--target-dir \
# 导入的目标目录如果存在则删除那个目录
--delete-target-dir \
# 相当于 -m,并行导入时 MapTask 的个数
--num-mappers \
--fields-terminated-by \
# 指定满足 sql 和条件的数据导入
# --query:增加检索条件部分数据抽取
# $CONDITIONS:数据分割条件的占位符
--query "$2" 'and $CONDITIONS;'

Sqoop 导入数据到 Hive 中的参数

1
2
3
4
5
6
7
8
9
# 一步将表结构和数据都导入到 hive 中
bin/sqoop import \
--connect jdbc 的 url 字符串\
--table mysql 中的表名\
--username 账号\
--password 密码\
--hive-import \
--m MapTask 的个数 \
--hive-database hive 中的数据库名 \

RDBMS 中的增量数据如何导入

1
2
3
4
5
6
7
# 指定判断检查的依据字段
--check-column 字段名 \
# 用来指定增量当如的模式(Mode),append 和 lastmodified
--incremental 导入模式 \
--last-value 上一次导入结束的时间 \
--m MapTask 的个数 \
--merge-key 主键

补充: 使用 --merge-key 合并模式,如果是新增的数据则增加,因为 incrementallastmodified 模式,那么当有数据更新了,而主键没有变,则会进行合并。

--check-column 字段名:当数据更新和修改,这个字段的时间也要随之变化,MySQL 中建表时,该字段修饰符、字段名 timeatamp default current_timestamp on update current_timestamp

Sqoop 导入导出 NULL 存储一致性问题

Hive 中的 NULL 在底层是以 \N 来存储的,而 MySQL 中的 NULL 在底层就是 NULL

为了保证数据两端的一致性

  • 在导出数据时采用 --input-null-string--input-null-non-string 两个参数
  • 在导入数据时采用 --null-string--null-non-string

Sqoop 数据导出一致性问题

场景:

如果 Sqoop 在导出数据到 MySQL 时,使用 4 个 Map 任务,过程中有 2 个任务失败,此时 MySQL 中存储了另外两个 Map 任务导入的数据,但是此时老板正好看到了这个报表数据。而开发工程师发现任务失败后,会调试问题并最终将全部数据正确的导入到 MySQL,那在后面老板再次看报表数据时,发现本次看到的数据与之前的不一致,这在生产环境中式不允许的。

解决方案一:

因为 Sqoop 将导出过程分解为多个事务,所以一个失败的导出作业可能会导致部分数据被提交到数据库。在某些情况下,这可能进一步导致后续作业由于插入冲突而失败,或者在其他情况下导致重复数据。您可以通过 --stage-table 选项指定一个暂存表(staging)来解决这个问题,这个表充当一个辅助表,用于暂存导出的数据。阶段数据最终在一个事务中移动到目标表。

官网:http://sqoop.apache.org/docs/1.4.6/SqoopUserGuide.html
Since Sqoop breaks down export process into multiple transactions, it is possible that a failed export job may result in partial data being committed to the database. This can further lead to subsequent jobs failing due to insert collisions in some cases, or lead to duplicated data in others. You can overcome this problem by specifying a staging table via the --staging-table option which acts as an auxiliary table that is used to stage exported data. The staged data is finally moved to the destination table in a single transaction.

使用 --stage-table 选项,将 HDFS 中的数据先导入到辅助表中,当 HDFS 中的数据导出成功后,辅助表中的数据在一个事务中导出到目标表中(也就是说,这个过程要么完全成功,要么完全失败)

为了能够使用 staging 这个选项,staging 表在运行任务前可能是空的,如果不为空就使用 --clear-staging-table 配置

如果 staging 表中有数据,并且使用了 --clear-staging-table 选项,Sqoop 执行导出任务前会删除 staging 表中所有的数据

注意:--direct 导入时 staging 方式是不可用的,使用了 --update-key 选项时 staging 方式也不可用

1
2
3
4
5
6
7
8
9
10
11
12
sqoop export \
--connect url \
--username root \
--password 123456 \
--table app_cource_study_report \
--columns watch_video_cnt,complete_video_cnt,dt \
--fields-terminated-by "\t" \
--export-dir "/user/hive/warehouse/tmp.db/app_cource_study_analysis_${day}" \
--staging-table app_cource_study_report_tmp \
--clear-staging-table \
--input-null-string '\\N' \
--null-non-string '\\N'

解决方案二:

设置 map 数量为 1 个(不推荐,面试官想要的答案不是这个)。

多个 Map 任务时,采用 --staging-table 方式,仍然可以解决数据一致性问题。

Sqoop 底层运行的任务是什么?

只有 Map 阶段,没有 Reduce 阶段的任务。默认是 4 个 MapTask。

MapTask 并行度设置大于 1 的问题?

并行度导入数据的时候需要指定根据哪个字段进行切分,该字段通常是主键或者是自增长不重复的数值类型字段,否则会报下面的错误:

Import failed: No primary key could be found for table. Please specify one with --split-by or perform a sequential import with '-m 1'.

那么就是说当 MapTask 并行度大于 1 时,下面两个参数要同时使用:

  • --split-by id:指定根据 id 字段进行切分;
  • --m n:指定 map 并行度 n 个。

Sqoop 一天导入多少数据?

每天 100 万活跃 --> 10 万订单,1 人 10 条,每天 1g 左右业务数据

Sqoop 每天将 1G 的数据量导入到数仓

Sqoop 数据导出的时候一次执行多长时间?

每天晚上 00:30 开始执行,Sqoop 任务一般情况 40-50 分钟的都有,取决于数据量(11.11,6.18 等活动在 1 个小时左右)。

Sqoop 任务 5 分钟 ~ 2 小时的都有,取决于数据量。

Sqoop 在导入数据的时候数据倾斜?

在说数据倾斜之前,我们设想数据并行抽数最理想的情况就是所有的并行实例同时完成,木桶原理,数据抽数时间的长短取决于耗时最长的那个实例。

由于各个实例被分配的数据量不均而导致分配到数据量较少的实例早早完成,而被分配大量数据的实例迟迟无法完成,导致整个作业运行时间很长的现象就是数据倾斜造成的。

数据倾斜概括为一句话:数据分配不均

在数据表没有符合要求的字段的情况下,我们需要自己临时简单创建理想的字段:

Sqoop 抽数的并行化主要设计到两个参数:

  • --num-mappers:启动 n 个 map 来并行导入数据,默认 4 个;
  • --split-by:按照某一列来切分表的工作单元。

具体原理是通过 ROWNUM() 生成一个严格均匀分布的字段,然后指定为分割字段。

Sqoop 数据导出 Parquet(项目中遇到的问题)

ADS 层数据用 Sqoop 往 MySQL 中导入数据的时候,如果用了 ORC(Parquet)不能导入,需转化成 text 格式。

  1. 创建临时表,把 Parquet 中表数据导入到临时表,把临时表导出到目标表用于可视化;
  2. Sqoop 里面有参数,可以直接把 Parquet 转换为 text;
  3. ADS 层建表的时候就不要建 Parquet 表。