Sqoop导入数据关于--split by 和 --m参数详细解析

本文探讨了使用sqoop进行数据导入时,通过调整split-by参数和-m参数来优化数据处理效率的方法。具体分析了不同参数设置下,map任务的划分方式及数据分布情况,指出在split-by字段为int类型且非连续时可能导致数据处理不均衡,提出了通过设置-m为1并使用时间字段作为分区字段的解决方案。
  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
    
    [hadoop@hadoop01 hive]$ hdfs dfs -cat /user/hive/warehouse/fei_hive.db/emp_import_partition/part-m-00000
    20/01/13 16:34:20 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
    7369	SMITH	CLERK	7902	1980-12-17 00:00:00.0	800.00	null	1
    7499	ALLEN	SALESMAN	7698	1981-02-20 00:00:00.0	1600.00	300.00	2
    7521	WARD	SALESMAN	7698	1981-02-22 00:00:00.0	1250.00	500.00	3
    7876	ADAMS	CLERK	7788	1983-01-12 00:00:00.0	1100.00	null	1
    7900	JAMES	CLERK	7698	1981-12-03 00:00:00.0	950.00	null	2
    7902	FORD	ANALYST	7566	1981-12-03 00:00:00.0	3000.00	null	3
    [hadoop@hadoop01 hive]$ hdfs dfs -cat /user/hive/warehouse/fei_hive.db/emp_import_partition/part-m-00001
    20/01/13 16:34:31 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
    7566	JONES	MANAGER	7839	1981-04-02 00:00:00.0	2975.00	null	4
    7654	MARTIN	SALESMAN	7698	1981-09-28 00:00:00.0	1250.00	1400.00	5
    7934	MILLER	CLERK	7782	1982-01-23 00:00:00.0	1300.00	null	4
    [hadoop@hadoop01 hive]$ hdfs dfs -cat /user/hive/warehouse/fei_hive.db/emp_import_partition/part-m-00002
    20/01/13 16:34:36 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
    7698	BLAKE	MANAGER	7839	1981-05-01 00:00:00.0	2850.00	null	6
    7782	CLARK	MANAGER	7839	1981-06-09 00:00:00.0	2450.00	null	7
    [hadoop@hadoop01 hive]$ hdfs dfs -cat /user/hive/warehouse/fei_hive.db/emp_import_partition/part-m-00003
    20/01/13 16:34:40 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
    7788	SCOTT	ANALYST	7566	1982-12-09 00:00:00.0	3000.00	null	8
    7839	KING	PRESIDENT	null	1981-11-17 00:00:00.0	5000.00	null	9
    7844	TURNER	SALESMAN	7698	1981-09-08 00:00:00.0	1500.00	0.00	10
    
    上面划分map区域就是(0,3],(3,5],(5,7],(7,10],
    

    上面遇到的问题就是当split-by是int类型但不是自增长的话,各个map分配的数据是不均衡的,可能会有些map很忙,有些map几乎没有数据处理的情况,数据多的时候,会拉数据的时候数据库出现奔溃的情况

  2. 当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
    
    [hadoop@hadoop01 ~]$ hdfs dfs -cat /user/hive/warehouse/fei_hive3.db/emp_import_partition/part-m-00000
    20/01/13 17:07:05 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
    7369	SMITH	CLERK	7902	1980-12-17 00:00:00.0	800.00	null	20
    7499	ALLEN	SALESMAN	7698	1981-02-20 00:00:00.0	1600.00	300.00	30
    7521	WARD	SALESMAN	7698	1981-02-22 00:00:00.0	1250.00	500.00	30
    7566	JONES	MANAGER	7839	1981-04-02 00:00:00.0	2975.00	null	20
    7654	MARTIN	SALESMAN	7698	1981-09-28 00:00:00.0	1250.00	1400.00	30
    7698	BLAKE	MANAGER	7839	1981-05-01 00:00:00.0	2850.00	null	30
    7782	CLARK	MANAGER	7839	1981-06-09 00:00:00.0	2450.00	null	10
    7788	SCOTT	ANALYST	7566	1982-12-09 00:00:00.0	3000.00	null	20
    7839	KING	PRESIDENT	null	1981-11-17 00:00:00.0	5000.00	null	10
    7844	TURNER	SALESMAN	7698	1981-09-08 00:00:00.0	1500.00	0.00	30
    7876	ADAMS	CLERK	7788	1983-01-12 00:00:00.0	1100.00	null	20
    7900	JAMES	CLERK	7698	1981-12-03 00:00:00.0	950.00	null	30
    7902	FORD	ANALYST	7566	1981-12-03 00:00:00.0	3000.00	null	20
    7934	MILLER	CLERK	7782	1982-01-23 00:00:00.0	1300.00	null	10
    

    但是可以使用时间字段作为分区字段(月,天),查询条件–query "select * from t where date=‘xxx’ ",时间可以写在一个文件去维护,从而可以使用shell脚本去循环查询,–m=1,这样就可以防止抽取数据的时候,把数据库拉死

<think>我们有一个任务:使用Sqoop进行增量数据导入,并学习columns、wherequery参数的用法。根据提供的引用,我们可以整合信息来构建一个教程。引用[1]展示了Sqoop将MySQL数据导入Hive的基本命令,但没有涉及增量导入query等参数。引用[2]介绍了Sqoop是用于Hadoop关系型数据库之间数据传输的工具,并提到以Oracle为例导入数据,但我们需要的是MySQL的例子。引用[3]给出了Sqoop的条件导入、增量导入以及在没有数字主键时如何使用文本列切分的例子,特别提到了使用`--split-by``-D`参数,还提到了`--where`参数。用户明确要求增量导入,以及columns、where、query参数的使用。在Sqoop中,增量导入有两种模式:`append``lastmodified`。-`append`模式:用于表中新增行,需要指定一个列(通常是自增ID)来跟踪新增加的行。-`lastmodified`模式:用于表中已有行的更新,需要指定一个时间戳列来跟踪更改。此外,我们还可以使用`--query`参数自定义SQL查询,同时使用`--where`参数进行简单的条件过滤,以及`--columns`指定要导入的列。下面我们逐步讲解:1.增量导入(IncrementalImport):Sqoop提供了`--incremental`参数来指定增量导入模式,同时需要指定:-`--check-column`:用于检查增量数据的列。-`--last-value`:上一次导入的该列的最大值(或时间戳)。示例(使用append模式):sqoopimport\--connectjdbc:mysql://hadoop:3306/db03\--usernamesqoop03\--password123456\--tablestudent\--target-dir/user/hive/warehouse/student\--incrementalappend\--check-columnid\--last-value100#表示上次导入的最后id是100,那么这次导入id>100的记录示例(使用lastmodified模式):sqoopimport\--connectjdbc:mysql://hadoop:3306/db03\--usernamesqoop03\--password123456\--tablestudent\--target-dir/user/hive/warehouse/student\--incrementallastmodified\--check-columnupdate_time\--last-value"2020-01-0100:00:00"#上次导入的最后时间戳,这次导入更新或新增的记录(注意:在lastmodified模式下,Sqoop会在导入后合并数据)2.`--where`参数:这个参数用于指定导入数据的条件,类似于SQL的WHERE子句,但不需要写WHERE关键字。示例:只导入age大于20的学生sqoopimport\--connectjdbc:mysql://hadoop:3306/db03\--usernamesqoop03\--password123456\--tablestudent\--where"age>20"\--target-dir/user/hive/warehouse/student_age_gt20注意:这个条件是在数据库服务器上执行的,所以效率较高。3.`--columns`参数:用于指定要导入的列,多个列名用逗号分隔(不要有空格)。示例:只导入idname列sqoopimport\--connectjdbc:mysql://hadoop:3306/db03\--usernamesqoop03\--password123456\--tablestudent\--columns"id,name"\--target-dir/user/hive/warehouse/student_columns4.`--query`参数:这个参数允许我们使用自定义的SQL查询来导入数据。当使用`--query`时,必须同时指定`--split-by`(用于并行切分的列)以及`--target-dir`,并且不能使用`--table`参数。示例:使用自定义查询导入数据,并且可以包含JOIN操作sqoopimport\--connectjdbc:mysql://hadoop:3306/db03\--usernamesqoop03\--password123456\--query'SELECTs.id,s.name,c.course_nameFROMstudentsJOINcoursecONs.course_id=c.idWHERE$CONDITIONS'\--split-bys.id\--target-dir/user/hive/warehouse/student_course注意:在查询中必须包含`$CONDITIONS`,这是Sqoop在并行导入时用来替换条件的占位符。同时,`--split-by`指定切分字段。5.结合增量导入query参数:我们可以将增量导入的条件放在自定义查询中,但通常我们也可以直接在where子句中处理。不过,Sqoop的增量导入参数--incremental,--check-column,--last-value)不能直接与--query一起使用。因此,如果要使用query进行增量导入,我们需要在查询语句中自行添加条件。示例:使用query实现append增量导入sqoopimport\--connectjdbc:mysql://hadoop:3306/db03\--usernamesqoop03\--password123456\--query"SELECT*FROMstudentWHEREid>100AND\$CONDITIONS"\--target-dir/user/hive/warehouse/student_incremental\--split-byid\-m1#这里使用-m1表示只有一个map任务,如果数据量大,我们可以使用多个map任务,并指定split-by但是,这样我们就需要自己记录上一次的id最大值,而不是使用Sqoop自动保存的last-value(Sqoop在增量导入后会自动更新last-value记录,但这里不会)。因此,更常见的是使用Sqoop提供的增量导入机制。6.关于引用[3]中提到的,如果没有数字主键,可以使用文本列切分,但需要增加`-D`参数-Dorg.apache.sqoop.splitter.allow_text_splitter=true示例:sqoopimport-Dorg.apache.sqoop.splitter.allow_text_splitter=true\--connectjdbc:mysql://192.168.58.203:3306/databasesname\--usernameroot\--password123\--tabletablename\--target-dir/sqoopdata/dirname\--delete-target-dir\--fields-terminated-by','\--split-byFieldName\#FieldName是一个文本类型的列-m2注意:使用`--query`时,如果查询中有WHERE子句,需要在条件中加入`$CONDITIONS`,并且整个查询语句用单引号括起来,以避免shell解释变量。在条件中,$CONDITIONS需要用双引号或者转义,如上例中我们使用了双引号,然后转义了美元符号(写成`\$CONDITIONS`),或者我们可以用单引号包裹整个查询,然后用`$CONDITIONS`(不转义),因为单引号会阻止变量扩展。最后,我们给出一个综合示例,使用增量导入(lastmodified模式)并指定列条件:sqoopimport\--connectjdbc:mysql://hadoop:3306/db03\--usernamesqoop03\--password123456\--tablestudent\--columnsid,name,age,update_time\--where"age>18"\--hive-import\--hive-tablemyhive.student1\--incrementallastmodified\--check-columnupdate_time\--last-value"2023-01-0100:00:00"\--merge-keyid#在lastmodified模式中,我们通常需要指定一个合并键,以便将新数据数据合并(对于更新操作)注意:`--merge-key`仅适用于lastmodified模式,它指定一个列(通常是主键)用于合并新记录已有记录(HDFS上)。总结教程:-增量导入通过`--incremental`指定模式,并配合`--check-column``--last-value`使用。-`--where`用于条件过滤,`--columns`用于选择列,`--query`用于自定义复杂查询。-使用`--query`时必须指定`--split-by``--target-dir`,并且不能使用`--table`。请根据实际数据表结构需求调整命令。</think> ### Sqoop 增量数据导入参数使用教程 #### 一、增量导入模式 Sqoop 提供两种增量导入模式: 1. **append 模式**(增量追加) 适用于带有自增主键的表,语法: ```bash sqoop import \ --connect jdbc:mysql://hadoop:3306/db03 \ --username sqoop03 --password 123456 \ --table student \ --incremental append \ # 增量模式 --check-column id \ # 检查增量列(如主键) --last-value 1000 \ # 上次导入的最大值 --hive-import ``` 2. **lastmodified 模式**(时间戳更新) 适用于含时间戳字段的表,语法: ```bash sqoop import \ --connect jdbc:mysql://hadoop:3306/db03 \ --username sqoop03 --password 123456 \ --table student \ --incremental lastmodified \ # 时间戳模式 --check-column update_time \ # 时间戳字段 --last-value "2023-01-01" \ # 上次导入的最晚时间 --merge-key id # 合并依据的键 ``` #### 二、核心参数详解 1. **`--columns` 参数** ```bash --columns "id,name,age" # 指定导入的字段 ``` **示例**:仅导入姓名年龄 ```bash sqoop import ... --columns "name,age" ``` 2. **`--where` 参数** ```bash --where "age > 18 AND dept='CS'" # SQL条件过滤 ``` **示例**:导入计算机系的学生 ```bash sqoop import ... --where "department='Computer Science'" ``` 3. **`--query` 参数** ```bash --query "SELECT * FROM student WHERE $CONDITIONS" ``` **注意事项**: - **必须包含 `$CONDITIONS`**(Sqoop分片占位符) - **必须指定 `--split-by`**(分片字段) - **禁用 `--table` 参数** **示例**:跨表联合查询 ```bash sqoop import \ --query "SELECT s.*, d.dept_name FROM student s JOIN department d ON s.dept_id=d.id WHERE $CONDITIONS" \ --split-by s.id \ # 指定分片字段 --target-dir /user/student_data ``` #### 三、综合应用实例 **场景**:增量导入年龄>20的计算机系学生数据Hive ```bash sqoop import \ --connect jdbc:mysql://hadoop:3306/db03 \ --username sqoop03 --password 123456 \ --query "SELECT id, name, age FROM student WHERE age > 20 AND department='CS' AND \$CONDITIONS" \ --split-by id \ # 分片依据 --incremental append \ # 增量模式 --check-column id \ # 增量检测列 --last-value 5000 \ # 上次导入的ID最大值 --hive-import \ --hive-table myhive.student_cs \ --m 4 # 并行任务数 ``` > **关键说明**: > 1. 使用 `\$CONDITIONS` 需用反斜杠转义(避免shell解析) > 2. `last-value` 会记录在 Sqoop metastore(`sqoop-job`)中 > 3. 增量导入后可用 `sqoop job --exec` 创建自动化任务 #### 四、常见问题解决 1. **非数值分片字段处理**: ```bash -Dorg.apache.sqoop.splitter.allow_text_splitter=true \ --split-by name # 使用文本字段分片 ``` 2. **Hive表字段映射**: ```bash --map-column-hive age=INT,name=STRING # 指定Hive数据类型 ``` 3. **空值处理**: ```bash --null-string '\\N' \ # 字符空值替换 --null-non-string '0' # 数字空值替换 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值