Sqoop导入导出过程原理

一、导入过程

       Sqoop是通过MapReduce作业进行导入工作,在作业中,会从表中读取一行行记录,然后将其写入HDFS

       在开始导入之前,Sqoop会通过JDBC来获得所需要的数据库元数据,例如,导入表的列名,数据类型等(第一步);接着这些数据库的数据类型(varchar,number等)会被映射成java类型(String,int等),根据这些信息,Sqoop会生成一个与表名同名的类用来完成反序列化的工作,保存表中的每一行记录(第二步);Sqoop启动MapReduce作用(第三步),MapReduce 中主要是对 InputFormat 和 OutputFormat 进行定制;启动的作业在input的过程中,会通过JDBC读取数据库表中的内容(第四步),这时,会使用Sqoop生成的类进行反序列化;最后再将这些记录写到HDFS中,在写入HDFS的过程中,同样会使用Sqoop生成的类进行序列化。

       Sqoop的导入作业通常不只是由一个Map任务完成,也就是说每个任务会获取表的一部分数据。如果只由一个Map任务完成导入的话,那么在第四步时,作业会通过JDBC执行如下SQL:

       SELECT col1,col2,...FROM table ;

       这样就能获得表的全部数据,如果需要多个Map任务来完成,那就必须对表进行水平切分,水平切分的依据通常会是表的主键。Sqoop在启动MapReduce作业时,会首先通过JDBC查询切分类的最大值和最小值,再根据启动的任务数(使用命令 -m指定)划分出每个任务所负责的数据,实际在第四步时,每个任务执行的SQL为:
        SELECT col1,col2,...FROM table WHERE id >=0 AND < 50000;

        SELECT col1,col2,...FROM table WHERE id >=50000 AND < 100000;

         ........

       使用Sqoop进行并行导入的话,切分列的数据会很大程度地影响性能,如果在均匀分布的情况下,性能最好。在最坏的情况下,数据严重倾斜,所有数据都集中在某一个切分区中,那么此时的性能与串行导入没有差别,所以,在导入之前,有必要对切分列的数据进行抽样检测,了解数据的分布。

       Sqoop可以对导入过程进行精细地控制,不用每次都导入一张表的所有字段。Sqoop允许我们知道表的列,在查询中加入WHERE自居,甚至可以自定义查询SQL语句,并且在SQL语句中,可以任意使用目标数据库所支持的函数。

       一旦数据导出完成后,这份数据就可被MapReduce程序所使用。但是我们知道,对于结构化的数据来说,Hive才是最适合处理的,所以自然而然也提供了相应的功能。

       将导入的数据存放到了HDFS中,将这份数据导入Hive之前,必须在Hive中创建该表,Sqoop提供了相应的命令:

sqoop create-hive-table  --connect jdbc: mysql : //master:3306/hive  --table DBS

--fields-terminated-by ','  --username root

       这时登录Hive会发现DBS表已经创建好了,但是没有数据。这时只需执行:

hive>LOAD DATA INPATH '/user/hadoop/DBS/part-r-00000' INTO TABLE DBS;

       这里要注意,由于Sqoop默认导出格式为逗号分隔,索引在Sqoop建表命令中,我们用  --fields-terminated-by ',' 指明Hive中DBS表的列分隔符。

       如果想直接从数据库将数据导入Hive中,也就是将上述3个步骤(导入HDFS,创建表,加载)合并为一个步骤,Sqoop也提供了相应的命令:

Sqoop import --connect  jdbc:mysql://master:3306/hive  --table DBS  --username root -m 1 --hive-import 

通过加上  --hive-import选项,Sqoop可以根据源数据库中的表结构来自动生成Hive表的结构,这样Sqoop就可方便地将数据直接导入Hive中。

二、导出过程

       与Sqoop导入功能相比,Sqoop的导出功能使用频率相对较低,一般都是将Hive的分析结果导出到关系型数据库以供数据分析师查看,生成报表等。

       在将Hive中的表导出到数据库时,必须在数据库中新建一张用来接收数据的表,需要导出的Hive表为 test_table,如下:

hive > DESC  test_table ;

OK

id   string 

Time taken:0.109 seconds

我们在mysql中新建一张用于接收数据的表,如下:

mysql>use test;

Database changed

mysql>create table test_received(id varchar(5));

       这里需要注意的是,在Hive中,字符串数据类型为STRING,但是在关系型数据库中,有可能是varchar(20),varchar(100),z这些必须根据情况自己指定,这也是必须由用户事先将表创建好的原因。接下来,就可以执行导入了,执行命令:

sqoop export --connect jdbc:mysql://master:3306/test  --table test_table --export-dir

/user/hive/warehouse/test_table  --username root -m 1 --fields-terminated-by  '\t'

       导出完毕后,就可以在Mysql中通过表test_received进行查询。对于上面这条导出命令,另外我们还需要将Hive表的列分隔符通过 --fields-terminated-by告知sqoop。

       在了解导入过程后,导出过程就变得容易理解了

       同样的,sqoop根据目标表的结构会生成一个java类(第一步和第二步),该类的作用为序列化和反序列化。接着会启动一个MapReduce作业(第三步),在作业中会用生成的java类从HDFS中读取数据(第四步),并生成一批INSERT语句,每条语句都会向MySQL的目标表中插入多条记录(第五步),这样读入的时候是并行,写入的时候也是并行,但是其写入性能会受限于数据库的写入性能。

你可能感兴趣的:(sqoop)