1.2 工作机制
将导入或导出命令翻译成mapreduce程序来实现
在翻译出的mapreduce中主要是对inputformat和outputformat进行定制
自定义
底层对自定义了mr,然后命令的方式,把这些命令翻译为mr
弄清楚:
$ tar zxvf /home/hadoop/soft/sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz -C /home/hadoop/app/
2、修改配置文件
$ cd $SQOOP_HOME/conf
$ mv sqoop-env-template.sh sqoop-env.sh
打开sqoop-env.sh并编辑下面几行:
为什么这里分开写,因为在很多其他的hadoop版本中,mr,hdfs,yarn是可以独立分开安装的。
export HADOOP_COMMON_HOME=/home/hadoop/apps/hadoop-2.6.1/
export HADOOP_MAPRED_HOME=/home/hadoop/apps/hadoop-2.6.1/
export HIVE_HOME=/home/hadoop/apps/hive-1.2.1
在sqoop-env.sh下面配置
export HADOOP_COMMON_HOME=/home/hadoop/app/hadoop-2.6.4/
export HADOOP_MAPRED_HOME=/home/hadoop/app/hadoop-2.6.4/
export HIVE_HOME=/home/hadoop/app/hive
在系统环境变量:
export SQOOP_HOME=/home/hadoop/app/sqoop-1.4.6
export PATH= P A T H : PATH: PATH:SQOOP_HOME/bin
如何需要导hadoop ,就需要配置HADOOP_HOME
如果需要导hive,就需要配置HIVE_HOME
如果需要导hbase,就需要配置HBASE_HOME
如果删除之后再重装的话,sqoop 会默认在hdfs 下面的/user/hadoop 创建一个sqoop相关的目录,需要手动的把这个目录删除,不然重装之后,会发生冲突,导致命令报错
3、加入mysql的jdbc驱动包
cp ~/app/hive/lib/mysql-connector-java-5.1.28.jar /home/hadoop/app/sqoop-1.4.6/lib/
4、验证启动
$ cd $SQOOP_HOME/bin
$ sqoop-version
预期的输出:
15/12/17 14:52:32 INFO sqoop.Sqoop: Running Sqoop version: 1.4.6
Sqoop 1.4.6 git commit id 5b34accaca7de251fc91161733f906af2eddbe83
Compiled by abe on Fri Aug 1 11:19:26 PDT 2015
到这里,整个Sqoop安装工作完成。
输入 sqoop help
Available commands:
codegen Generate code to interact with database records
create-hive-table Import a table definition into Hive
eval Evaluate a SQL statement and display the results
export Export an HDFS directory to a database table
help List available commands
import Import a table from a database to HDFS
import-all-tables Import tables from a database to HDFS
import-mainframe Import datasets from a mainframe server to HDFS
job Work with saved jobs
list-databases List available databases on a server
list-tables List available tables in a database
merge Merge results of incremental imports
metastore Run a standalone Sqoop metastore
version Display version information
1.4 Sqoop的数据导入
“导入工具”导入单个表从RDBMS到HDFS。表中的每一行被视为HDFS的记录。所有记录都存储为文本文件的文本数据(或者Avro、sequence文件等二进制数据)
1.4.1 语法
下面的语法用于将数据导入HDFS。
$ sqoop import (generic-args) (import-args)
1.4.2 示例
Mysql的建表语句
CREATE TABLE testdb.emp04(
empno INT,
ename VARCHAR(50),
job VARCHAR(50),
mgr INT,
hiredate DATE,
sal DECIMAL(7,2),
comm decimal(7,2),
deptno INT
) ;
INSERT INTO emp03 values(7369,‘SMITH’,‘CLERK’,7902,‘1980-12-17’,800,NULL,20);
INSERT INTO emp03 values(7499,‘ALLEN’,‘SALESMAN’,7698,‘1981-02-20’,1600,300,30);
INSERT INTO emp03 values(7521,‘WARD’,‘SALESMAN’,7698,‘1981-02-22’,1250,500,30);
INSERT INTO emp03 values(7566,‘JONES’,‘MANAGER’,7839,‘1981-04-02’,2975,NULL,20);
INSERT INTO emp03 values(7654,‘MARTIN’,‘SALESMAN’,7698,‘1981-09-28’,1250,1400,30);
INSERT INTO emp03 values(7698,‘BLAKE’,‘MANAGER’,7839,‘1981-05-01’,2850,NULL,30);
INSERT INTO emp03 values(7782,‘CLARK’,‘MANAGER’,7839,‘1981-06-09’,2450,NULL,10);
INSERT INTO emp03 values(7788,‘SCOTT’,‘ANALYST’,7566,‘1987-04-19’,3000,NULL,20);
INSERT INTO emp03 values(7839,‘KING’,‘PRESIDENT’,NULL,‘1981-11-17’,5000,NULL,10);
INSERT INTO emp03 values(7844,‘TURNER’,‘SALESMAN’,7698,‘1981-09-08’,1500,0,30);
INSERT INTO emp03 values(7876,‘ADAMS’,‘CLERK’,7788,‘1987-05-23’,1100,NULL,20);
INSERT INTO emp03 values(7900,‘JAMES’,‘CLERK’,7698,‘1981-12-03’,950,NULL,30);
INSERT INTO emp03 values(7902,‘FORD’,‘ANALYST’,7566,‘1981-12-03’,3000,NULL,20);
INSERT INTO emp03 values(7934,‘MILLER’,‘CLERK’,7782,‘1982-01-23’,1300,NULL,10);
查看输出的结果:
— select * from testdb.emp01 limit 10;
Mysql 里面 的emp03的数据导入到hdfs
导入关系型数据库的表数据到HDFS
下面的命令用于从MySQL数据库服务器中的emp表导入HDFS。
$bin/sqoop import
–connect jdbc:mysql://huawei:3306/testdb
–username root
–password root
–table emp06
–m 1
注意哦:这里并没有写导入到hdfs的哪个目录下,其实是有一个默认地址的,这个地址的路径是 /user/hadoop/emp03
通过下载导入之后的数据,吃惊的发现数据都被以逗号分割了
通过下面的命令查看导入的结果
$ $HADOOP_HOME/bin/hadoop fs -cat /user/hadoop/emp/part-m-00000
导入关系表到HIVE
bin/sqoop import --connect jdbc:mysql://huawei:3306/testdb --username root --password root --table emp04 --hive-import --m 1
刚才我报了一个错,需要把/user/hadoop/emp删除才能运行,
17/10/14 23:36:32 ERROR tool.ImportTool: Encountered IOException running import job: org.apache.hadoop.mapred.FileAlreadyExistsException: Output directory hdfs://huawei:8020/user/hadoop/emp03already exists
需要先把这个目录删除掉:
–hdfs hdfs dfs -r hdfs://huawei:8020/user/hadoop/emp
所有我们可以窥看出sqoop导入hive的工作流程;
1.mr程序把数据从mysql导入到hdfs的/user/hadoop/emp
2.创建一个和mysql对应上的hive表
3.把数据从/user/hadoop/emp03目录,load到hive表
导入到HDFS指定目录
在导入表数据到HDFS使用Sqoop导入工具,我们可以指定目标目录。
以下是指定目标目录选项的Sqoop导入命令的语法。
–target-dir
下面的命令是用来导入emp表数据到’/queryresult’目录。
bin/sqoop import
–connect jdbc:mysql://huawei:3306/testdb
–username root
–password root
–target-dir /sqooptarget1703
–table emp04 --m 1
注意: 这个目录显然是hdfs上面没有的目录,因为–target-dir /sqooptarget \ 映射成outPutPath
下面的命令是用来验证 /queryresult 目录中 emp_add表导入的数据形式。
$HADOOP_HOME/bin/hadoop fs -cat /queryresult/part-m-*
导入表数据子集
我们可以导入表的使用Sqoop导入工具,"where"子句的一个子集。它执行在各自的数据库服务器相应的SQL查询,并将结果存储在HDFS的目标目录。
where子句的语法如下。
–where
下面的命令用来导入emp表数据的子集。导入部门编号是30的员工信息:
bin/sqoop import
–connect jdbc:mysql://huawei:3306/testdb
–username root
–password root
–where “deptno=30”
–target-dir /wheresqooptarget1706
–table emp04 --m 1
按需导入
bin/sqoop import
–connect jdbc:mysql://huawei:3306/testdb
–username root
–password root
–target-dir /wherequery1706_a
–query ‘select empno,ename from emp04 WHERE empno>7500 and $CONDITIONS’
–split-by empno
–fields-terminated-by ‘\t’
–m 1
下面的命令用来验证数据从emp表导入/wherequery目录
$HADOOP_HOME/bin/hadoop fs -cat /wherequery1703_b /part-m-*
和实际项目有一定联系的场景:
数据是每隔一段时间就会有新的数据,数据其实并不需要一次性的全部导入,每隔一段时间只需要把这些新增的数据导入到hdfs即可。
增量导入
增量导入是仅导入新添加的表中的行的技术。
它需要添加‘incremental’, ‘check-column’, 和 ‘last-value’选项来执行增量导入。
下面的语法用于Sqoop导入命令增量选项。
–incremental
–check-column
–last value
假设新添加的数据转换成emp表如下:
INSERT INTO emp06 values(7937,‘kobe_nb_1’,‘CLERK’,7900,‘1984-02-23’,2500,NULL,30);
INSERT INTO emp06 values(7938,‘kobe_nb_2’,‘CLERK’,7900,‘1984-02-23’,2500,NULL,30);
下面的命令用于在EMP表执行增量导入。
bin/sqoop import
–connect jdbc:mysql://huawei:3306/testdb
–username root
–password root
–table emp03 --m 1
–incremental append
–check-column empno
–target-dir /sqooptarget1701c
–last-value 7936
bin/sqoop import
–connect jdbc:mysql://huawei:3306/testdb
–username root
–password root
–table emp06 --m 1
–incremental append
–check-column empno
–last-value 7936
还有一种增量导入的方式给根据导入的时间戳来判断 ,可以在文档中了解下。
以下命令用于从emp表导入HDFS emp/ 目录的数据验证。
$ $HADOOP_HOME/bin/hadoop fs -cat /user/hadoop/emp/part-m-*
它用逗号(,)分隔 emp_add表数据和字段。
1201, gopal, manager, 50000, TP
1202, manisha, preader, 50000, TP
1203, kalil, php dev, 30000, AC
1204, prasanth, php dev, 30000, AC
1205, kranthi, admin, 20000, TP
1206, satish p, grp des, 20000, GR
下面的命令是从表emp03用来查看修改或新添加的行
$ $HADOOP_HOME/bin/hadoop fs -cat /emp/part-m-*1
这表示新添加的行用逗号(,)分隔emp表的字段。
1206, satish p, grp des, 20000, GR
1.5 Sqoop的数据导出
将数据从HDFS导出到RDBMS数据库
导出前,目标表必须存在于目标数据库中。
默认操作是从将文件中的数据使用INSERT语句插入到表中
更新模式下,是生成UPDATE语句更新表数据
注意:从mysql–> hive ,不需要我们创建hive表
但是从hdfs --> mysql 需要你手动的创建对应的mysql表
语法
以下是export命令语法。
$ sqoop export (generic-args) (export-args)
示例
数据是在HDFS 中“EMP/”目录的emp_data文件中。所述emp_data如下:
1201, gopal, manager, 50000, TP
1202, manisha, preader, 50000, TP
1203, kalil, php dev, 30000, AC
1204, prasanth, php dev, 30000, AC
1205, kranthi, admin, 20000, TP
1206, satish p, grp des, 20000, GR
1、首先需要手动创建mysql中的目标表
$ mysql
mysql> USE db;
mysql> CREATE TABLE employee (
id INT NOT NULL PRIMARY KEY,
name VARCHAR(20),
deg VARCHAR(20),
salary INT,
dept VARCHAR(10));
2、然后执行导出命令
bin/sqoop export
–connect jdbc:mysql://huawei:3306/testdb
–username root
–password root
–table emp01
–export-dir /wheresqooptarget/
3、验证表mysql命令行。
mysql>select * from employee;
项目中,是如何把新增用户导入到对应的mysql表中去的
具体的作业怎么执行 有更强大的工具,azkaban ,自己写的shell + crontab
1.6 Sqoop作业
注:Sqoop作业——将事先定义好的数据导入导出任务按照指定流程运行
语法
以下是创建Sqoop作业的语法。
$ sqoop job (generic-args) (job-args)
[-- [subtool-name] (subtool-args)]
$ sqoop-job (generic-args) (job-args)
[-- [subtool-name] (subtool-args)]
创建作业(–create)
在这里,我们创建一个名为myjob,这可以从RDBMS表的数据导入到HDFS作业。
bin/sqoop job --create myimportjob – import --connect jdbc:mysql://hdp-node-01:3306/test --username root --password root --table emp03–m 1
该命令创建了一个从db库的employee表导入到HDFS文件的作业。
验证作业 (–list)
‘–list’ 参数是用来验证保存的作业。下面的命令用来验证保存Sqoop作业的列表。
$ sqoop job --list
它显示了保存作业列表。
Available jobs:
myimportjob
检查作业(–show)
‘–show’ 参数用于检查或验证特定的工作,及其详细信息。以下命令和样本输出用来验证一个名为myjob的作业。
$ sqoop job --show myjob
它显示了工具和它们的选择,这是使用在myjob中作业情况。
Job: myjob
Tool: import Options:
direct.import = true
codegen.input.delimiters.record = 0
hdfs.append.dir = false
db.table = employee
…
incremental.last.value = 1206
…
执行作业 (–exec)
‘–exec’ 选项用于执行保存的作业。下面的命令用于执行保存的作业称为myjob。
$ sqoop job --exec myjob
它会显示下面的输出。
10/08/19 13:08:45 INFO tool.CodeGenTool: Beginning code generation
…
1.7 Sqoop的原理
概述
Sqoop的原理其实就是将导入导出命令转化为mapreduce程序来执行,sqoop在接收到命令后,都要生成mapreduce程序
使用sqoop的代码生成工具可以方便查看到sqoop所生成的java代码,并可在此基础之上进行深入定制开发
代码定制
以下是Sqoop代码生成命令的语法:
$ sqoop-codegen (generic-args) (codegen-args)
$ sqoop-codegen (generic-args) (codegen-args)
示例:以USERDB数据库中的表emp来生成Java代码为例。
下面的命令用来生成导入
$ sqoop-codegen
–import
–connect jdbc:mysql://localhost/userdb
–username root \
–table emp
如果命令成功执行,那么它就会产生如下的输出。
14/12/23 02:34:40 INFO sqoop.Sqoop: Running Sqoop version: 1.4.5
14/12/23 02:34:41 INFO tool.CodeGenTool: Beginning code generation
……………….
14/12/23 02:34:42 INFO orm.CompilationManager: HADOOP_MAPRED_HOME is /usr/local/hadoop
Note: /tmp/sqoop-hadoop/compile/9a300a1f94899df4a9b10f9935ed9f91/emp.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
14/12/23 02:34:47 INFO orm.CompilationManager: Writing jar file: /tmp/sqoop-hadoop/compile/9a300a1f94899df4a9b10f9935ed9f91/emp.jar
验证: 查看输出目录下的文件
$ cd /tmp/sqoop-hadoop/compile/9a300a1f94899df4a9b10f9935ed9f91/
$ ls
emp.class
emp.jar
emp.java
如果想做深入定制导出,则可修改上述代码文件
1.8 Mysql的建表语句
CREATE TABLE emp_export(
empno INT,
ename VARCHAR(50),
job VARCHAR(50),
mgr INT,
hiredate DATE,
sal DECIMAL(7,2),
comm decimal(7,2),
deptno INT
) ;
INSERT INTO emp03values(7369,‘SMITH’,‘CLERK’,7902,‘1980-12-17’,800,NULL,20);
INSERT INTO emp03values(7499,‘ALLEN’,‘SALESMAN’,7698,‘1981-02-20’,1600,300,30);
INSERT INTO emp03values(7521,‘WARD’,‘SALESMAN’,7698,‘1981-02-22’,1250,500,30);
INSERT INTO emp03values(7566,‘JONES’,‘MANAGER’,7839,‘1981-04-02’,2975,NULL,20);
INSERT INTO emp03values(7654,‘MARTIN’,‘SALESMAN’,7698,‘1981-09-28’,1250,1400,30);
INSERT INTO emp03values(7698,‘BLAKE’,‘MANAGER’,7839,‘1981-05-01’,2850,NULL,30);
INSERT INTO emp03values(7782,‘CLARK’,‘MANAGER’,7839,‘1981-06-09’,2450,NULL,10);
INSERT INTO emp03values(7788,‘SCOTT’,‘ANALYST’,7566,‘1987-04-19’,3000,NULL,20);
INSERT INTO emp03values(7839,‘KING’,‘PRESIDENT’,NULL,‘1981-11-17’,5000,NULL,10);
INSERT INTO emp03values(7844,‘TURNER’,‘SALESMAN’,7698,‘1981-09-08’,1500,0,30);
INSERT INTO emp03values(7876,‘ADAMS’,‘CLERK’,7788,‘1987-05-23’,1100,NULL,20);
INSERT INTO emp03values(7900,‘JAMES’,‘CLERK’,7698,‘1981-12-03’,950,NULL,30);
INSERT INTO emp03values(7902,‘FORD’,‘ANALYST’,7566,‘1981-12-03’,3000,NULL,20);
INSERT INTO emp03values(7934,‘MILLER’,‘CLERK’,7782,‘1982-01-23’,1300,NULL,10);