Sqoop导入数据–split by 和 --m(大于1)配合使用
split-by 根据不同的参数类型有不同的切分方法; 如int型,Sqoop会取最大和最小split-by字段值,然后根据传入的num-mappers来 确定划分几个区域。 比如select max(split_by),min(split-by) from得到的max(split-by)和min(split-by)分别为1000和1,而num-mappers(-m)为2的话,则会分成两个区域 (1,500)和(501-1000),同时也会分成2个sql给2个map去进行导入操作, 分别为select XXX from table where split-by>=1 and split-by<500和select XXX from table where split-by>=501 and split-by<=1000. 最后每个map各自获取各自SQL中的数据进行导入工作。
sqoop import \
--connect jdbc:mysql://hadoop01:3306/feidata \
--username xxx \
--password xxx \
--table emp \
--hive-overwrite \
--delete-target-dir \
--hive-import --hive-database fei_hive \
--hive-table emp_import_partition \
--fields-terminated-by '\t' \
--split-by deptno
如果不设置的话,默认是–m=4
上面遇到的问题就是当split-by是int类型但不是自增长的话,各个map分配的数据是不均衡的, 可能会有些map很忙,有些map几乎没有数据处理的情况, 数据多的时候,会拉数据的时候数据库出现奔溃的情况
当split-by不是int型时出现如上场景中的问题。目前想到的解决办法是: 将-m设置称1,split-by不设置,即只有一个map运行, 缺点是不能并行map录入数据,( 注意,当-m设置的值大于1时,split-by必须设置字段)数据多的时候,也会在拉数据的时候数据库出现奔溃的情况。
sqoop import \
--connect jdbc:mysql://hadoop01:3306/feidata \
--username xxx \
--password xxx\
--table emp \
--hive-overwrite \
--delete-target-dir \
--hive-import --hive-database fei_hive \
--hive-table emp_import_partition \
--fields-terminated-by '\t' \
--split-by hiredate
--m 1
但是可以使用时间字段作为分区字段(月,天), 查询条件–query "select * from t where date=‘xxx’ ",时间可以写在一个文件去维护,从而可以使用shell脚本去循环查询,–m=1,这样就可以防止抽取数据的时候,把数据库拉死
|