
Sqoop 面试题解析
Sqoop 参数
Sqoop 导入数据到 HDFS 中的参数
1 | /opt/module/sqoop/bin/sqoop import \ |
Sqoop 导入数据到 Hive 中的参数
1 | 一步将表结构和数据都导入到 hive 中 |
RDBMS 中的增量数据如何导入
1 | 指定判断检查的依据字段 |
补充: 使用 --merge-key
合并模式,如果是新增的数据则增加,因为 incremental
是 lastmodified
模式,那么当有数据更新了,而主键没有变,则会进行合并。
--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 | sqoop export \ |
解决方案二:
设置 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 格式。
- 创建临时表,把 Parquet 中表数据导入到临时表,把临时表导出到目标表用于可视化;
- Sqoop 里面有参数,可以直接把 Parquet 转换为 text;
- ADS 层建表的时候就不要建 Parquet 表。