Sqoop中的import与export都是基于Hadoop而言的。在本篇文章中,将对Sqoop中的import与export进行详细介绍;同时对sqoop job的使用,eval与options-file的使用进行介绍
Sqoop import
Sqoop import命令详解
如何查看帮助
- 帮助文档
http://archive.cloudera.com/cdh5/cdh/5/sqoop-1.4.6-cdh5.7.0/SqoopUserGuide.html
建议:sqoop的使用不看官方文档,太乱 - 直接使用 –help 命令进行查看
- 帮助文档
查看使用帮助
$>sqoop import --help
将MySQL中的数据导入到HDFS
sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp
产生报错:
原因:少个jar包,需要将java-json.jar包拷贝到lib目录下
$>cp java-json.jar $SQOOP_HOME/lib/
导入jar包之后,重新导入
在运行过程中,扔到了YARN上去执行作业
原因:Sqoop的底层是MapReduce任务的执行,因此是跑在Yarn上的分析打印的控制台log:
打印了信息SELECT t.* FROM
emp
AS t LIMIT 1
执行这句话的目的:去查看emp这张表是否在数据库中存在
不相信,我们可以直接在mysql中进行执行select * from empsb limit 1; // 会报错,因为empsb这张表在数据库中不存在 select * from emp limit 1; // 没报错,因为empsb这张表在数据库中存在
打印信息HADOOP_MAPRED_HOME is /opt/app/hadoop-2.6.0-cdh5.7.0
- 打印信息Writing jar file: /tmp/sqoop-hadoop/compile/3b2ff5cf1612195cd5cbd6b29c3e75e5/emp.jar
根据表的名字,生成一个相关的jar包 - 打印信息number of splits:4
why? 因为默认情况下就是4个map,会生成4个文件
我们可以通过-m参数进行指定map个数
导入成功之后,查看HDFS上的数据
使用–delete-target-dir参数
执行的过程中,删除已经存在的输出目录
(因为如果输出的目录已经存在了,会报错,和执行MR的时候是一样的)sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp \ --delete-target-dir
使用–mapreduce-job-name命令
指定输出jar包的名字sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp \ --delete-target-dir \ --mapreduce-job-name emp-all
通过Web界面可以发现不同:
只抽取指定字段
sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp \ --delete-target-dir \ --mapreduce-job-name emp-all \ --columns "EMPNO,ENAME,JOB,SAL,COMM"
指定输出到HDFS的路径
sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp \ --delete-target-dir \ --mapreduce-job-name emp-all \ --columns "EMPNO,ENAME,JOB,SAL,COMM" \ --target-dir EMP_COLUMN
使用-m参数指定map个数
sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp \ -m 1 \ --delete-target-dir \ --mapreduce-job-name emp-all \ --columns "EMPNO,ENAME,JOB,SAL,COMM" \ --target-dir EMP_COLUMN
Sqoop import命令条件过滤详解
使用–where参数来限定工资条件(SAL > 2000)
sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp \ -m 1 \ --delete-target-dir \ --mapreduce-job-name emp-all \ --columns "EMPNO,ENAME,JOB,SAL,COMM" \ --target-dir EMP_COLUMN \ --where "SAL>2000"
使用–query 写sql语句 来执行
sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ -m 1 \ --delete-target-dir \ --mapreduce-job-name emp-all \ --target-dir EMP_COLUMN \ --query 'select * from emp where sal>2000 and $CONDITIONS'
注意:
- 使用–query写sql语句,就不需要–table 去指定表名了,也不需要–columns该参数去指定输出列了,不然会报错
- 而且必须在sql语句的最后加 $CONDITIONS,不然会报错
导入没有主键的表数据到HDFS,并且使用多个map来运行
创建没有主键的表salgrage,并导入数据
create table salgrade ( grade numeric, losal numeric, hisal numeric ); insert into salgrade values (1, 700, 1200); insert into salgrade values (2, 1201, 1400); insert into salgrade values (3, 1401, 2000); insert into salgrade values (4, 2001, 3000); insert into salgrade values (5, 3001, 9999);
导入
sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table salgrade
报错:
分析错误信息:对于这张表,没有主键能够被找到
分析报错原因:
- 因为map的默认数量为4,而salgrage里有5条数据,那么就必然涉及到数据的切分
- 但是因为没主键,如何去切分数据呢?
解决方案:
- 设置map个数为1
- 设置切分数据的字段设置切分的字段为GRADE 去导入:
sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table salgrade \ --split-by GRADE \ --delete-target-dir \ -m 2
查看HDFS上的数据:
$>hadoop fs -ls salgrage $>hadoop fs -text salgrade/*
对分隔符及空值的处理
介绍
–null-non-string ‘0’ \ 非String类型的null值用0替代
–null-string ” \ String类型的null值用’ ‘替代分隔符及空值处理
sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp \ -m 1 \ --delete-target-dir \ --mapreduce-job-name emp-all \ --columns "EMPNO,ENAME,JOB,SAL,COMM" \ --target-dir EMP_COLUMN_SPLIT \ --fields-terminated-by '\t' \ --null-non-string '0' \ --null-string ''
查看HDFS上的数据
$>hadoop fs -text EMP_COLUMN_SPLIT/part-m-00000
direct模式
使用
sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp \ -m 1 \ --delete-target-dir \ --mapreduce-job-name emp-all \ --columns "EMPNO,ENAME,JOB,SAL,COMM" \ --target-dir EMP_COLUMN_SPLIT \ --fields-terminated-by '\t' \ --null-non-string '0' \ --null-string '' \ --direct
浅析direct模式
direct模式底层使用了工具mysqlimport
当数据量不大,使用该模式跑起来没什么意义观察日志信息:
使用的manager为DirectMySQLManager17/10/21 15:18:18 WARN manager.DirectMySQLManager: Direct-mode import from MySQL does not support column
而不使用–direct模式,使用的manager则为MySQLManager
17/10/21 15:15:15 WARN manager.MySQLManager: It looks like you are importing from mysql. 17/10/21 15:15:15 WARN manager.MySQLManager: This transfer can be faster! Use the --direct
同时,值得注意的信息有:direct模式支持全部列导入的模式
对各种数据库的支持
增量导入
上面所介绍的数据导入方式都是:全量的导入方式
增量导入介绍
增量导入的使用
sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp \ -m 1 \ --mapreduce-job-name emp-all \ --columns "EMPNO,ENAME,JOB,SAL,COMM" \ --target-dir EMP_APPEND \ --fields-terminated-by '\t' \ --null-non-string '0' \ --null-string '' \ --check-column EMPNO \ --incremental append \ --last-value 7900
–last-value 7900 表示只取比7900大的数据,进行导入
注意
–incremental append 与 –delete-target-dir之间不能共用,因为是互斥的
导入MySQL数据到Hive表
使用参数–create-hive-table导入
sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp \ -m 1 \ --delete-target-dir \ --hive-import \ --create-hive-table \ --hive-table emp_import
报错:
说是找不到类,Jar包缺失解决办法:
$>cp $HIVE_HOME/lib/hive-common-1.1.0-cdh5.7.0.jar $SQOOP_HOME/lib $>cp $HIVE_HOME/lib/hive-shims-* $SQOOP_HOME/lib
重新导入
查看导入到Hive表的表结构:
hive>desc emp_import;
会发现有些字段的类型发生了改变,从double类型变成了int类型
使用–hive-import参数导入
删除Hive表之后,再度执行一次:sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp \ -m 1 \ --delete-target-dir \ --hive-import \ --hive-table emp_import
补充
- –create-hive-table 生产上不建议使用,字段类型和我们自己预想会有差别
而且只能执行一次(再执行一次,会报表已经存在的错误) - –hive-import 在导入的时候,会默认去读Hive的default数据库
–hive-table 不需要自己先去Hive中创建表,执行的时候,会自动帮我们去创建相应的表
- –create-hive-table 生产上不建议使用,字段类型和我们自己预想会有差别
导入分区表到Hive中
介绍
分区表导入
增量导入的方式(综合前面的import使用命令)sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp \ --mapreduce-job-name emp-all \ --fields-terminated-by '\t' \ --null-non-string '0' \ --null-string '' \ --check-column EMPNO \ --incremental append \ --last-value 7900 \ --hive-import \ --hive-table emp_import \ --hive-partition-key 'event_month' \ --hive-partition-value '2017-10-08'
导入成功
Sqoop export
导出HDFS数据到MySQL
创建MySQL表
导入数据到MySQL之前,需要现在MySQL上创建一个表
导入一个空表,但是有表结构mysql>create table emp_demo as select * from emp where 1=2; mysql>select * from emp_demo;
导出
导出之前,先从MySQL全量导入一张表到HDFS中,并命名为empsqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp \ --target-dir emp \ --fields-terminated-by '\t'
开始导出:
sqoop export \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp_demo \ --fields-terminated-by '\t' \ --export-dir /user/hadoop/emp
成功导出到MySQL
注意每操作一次,数据就会直接叠加上去
导出Hive数据到MySQL
前置准备
事先先导入数据到Hive表中,自己设置分隔符sqoop import \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp \ --fields-terminated-by '\t' \ --delete-target-dir \ --hive-import \ --hive-table emp_import
导出
sqoop export \ --connect jdbc:mysql://localhost:3306/sqoop \ --username root \ --password root \ --table emp_demo \ --export-dir /user/hive/warehouse/emp_import \ --fields-terminated-by '\t' \ -m 1
注意导出的时候,分隔符需要自己去设置,不然又要对不上,可能会报错
eval与options-file
eval的使用
执行一个SQL语句,并将结果展示出来在控制台上
```
sqoop eval \
--connect jdbc:mysql://localhost:3306/sqoop \
--username root \
--password root \
--query "select * from emp where deptno=10"
```
options-file的使用
在工作中推荐这样子使用
```
$>vi emp.opt
import
--connect
jdbc:mysql://localhost:3306/sqoop
--username
root
--password
root
--table
emp
-m
1
--delete-target-dir
--target-dir
EMP_OPTIONS_FILE
```
执行sqoop
$>sqoop –options-file emp.opt
执行成功:
Sqoop job
sqoop job --create myjob -- \
import --connect jdbc:mysql://localhost:3306/sqoop \
--username root \
--password root \
--delete-target-dir \
--table emp
$>sqoop job --list 列出创建的sqoopjob
$>sqoop job --show myjob
$>sqoop job --exec myjob 执行创建的job
$>hadoop fs -text emp/part* 查看HDFS上的数据
sqoop job创建成功,可以执行: