Sqoop使用import-all并行导入含无主键表的全表方案问询
全表并行导入解决方案(针对存在无主键表的MySQL Schema场景)
首先说明报错原因:主流数据导入工具(如Sqoop)默认用主键作为分片列拆分任务分配给多个mapper,无主键表没有默认分片列,多mapper场景下无法拆分任务就会触发导入失败。以下是可落地的三种解决方案:
方案1:为无主键表指定自定义分片列
如果无主键表存在数值型、分布相对均匀的非主键字段(比如非主键自增字段、整数类型的创建时间戳等),可以单独为这些表指定--split-by参数声明分片列,即可正常使用多mapper并行导入。
示例命令:
# 有主键表正常导入,无需额外配置 sqoop import --connect jdbc:mysql://<数据库地址>/<目标schema名> --username <账号> --password <密码> --table <有主键表名> --m 4 # 无主键表指定分片列导入 sqoop import --connect jdbc:mysql://<数据库地址>/<目标schema名> --username <账号> --password <密码> --table <无主键表名> --split-by <均匀分布的非主键字段名> --m 4
如果要一次性导入全库,可以写shell脚本遍历所有表,自动判断表是否有主键,有主键的走默认导入逻辑,无主键的指定对应分片列导入。
方案2:开启无主键表随机分片
如果无主键表没有合适的分片列,可以通过指定常量分片列+自定义边界的方式实现多mapper导入:
注意:该方式会先做全表扫描再拆分任务,超大数据量表场景会有一定性能损耗
示例命令:
sqoop import --connect jdbc:mysql://<数据库地址>/<目标schema名> --username <账号> --password <密码> --table <无主键表名> --split-by 1 --boundary-query "select 1, <mapper数量>" --m <mapper数量>
该命令会将表数据随机拆分为对应数量的分片分配给多个mapper执行,不需要表本身有合适的分片字段。
方案3:混合并行策略
如果不想单独适配每个无主键表,可以用表级并行+表内并行的混合策略实现全库高效导入:
- 有主键表使用多mapper实现表内并行,充分利用资源
- 无主键表每个表单独分配1个mapper,同时并行启动多个无主键表的导入任务,实现表级并行
简化版shell脚本示例:
# 拉取schema下所有表名 tables=$(mysql -h<数据库地址> -u<账号> -p<密码> <目标schema名> -e "show tables;" | grep -v Tables_in) for table in $tables do # 判断当前表是否存在主键 has_pk=$(mysql -h<数据库地址> -u<账号> -p<密码> <目标schema名> -e "SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='<目标schema名>' AND TABLE_NAME='$table' AND COLUMN_KEY='PRI';" | grep -v COUNT) if [ $has_pk -gt 0 ];then # 有主键表开启表内4并行导入 sqoop import --connect jdbc:mysql://<数据库地址>/<目标schema名> --username <账号> --password <密码> --table $table --m 4 & else # 无主键表单mapper导入,多表同时运行实现并行 sqoop import --connect jdbc:mysql://<数据库地址>/<目标schema名> --username <账号> --password <密码> --table $table --m 1 & fi done wait
内容的提问来源于stack exchange,提问作者Lavanya varma
相关产品推荐
相关产品推荐

