1、sqoop使用
在学习sqoop使用之前,我们需要查看sqoop都是可以完成什么任务,通过键入:sqoop help,我们就可以看到sqoop可以提供的服务。在项目中,我们主要使用的是sqoop import服务,在使用的过程中,我们还会经历很多定制修改,讲逐一讲解。
1.1将数据从数据库导入到hadoop中
导入指令:sqoop import –connect jdbc:mysql://hostname:port/database –username root –password 123456 –table example –m 1。在这里讲解一下指令的构成,如下:
1、--connect jdbc:mysql://hostname:port/database指定mysql数据库主机名和端口号和数据库名;
2、--username root 指定数据库用户名
3、--password 123456 指定数据库密码
4、--table example mysql中即将导出的表
5、-m 1 指定启动一个map进程,如果表很大,可以启动多个map进程
6、导入到HDFS中的路径 默认:/user/grid/example/part-m-00000
注意:默认情况下,Sqoop会将我们导入的数据保存为逗号分隔的文本文件。如果导入数据的字段内容存在分隔符,则我们可以另外指定分隔符、字段包围字符和转义字符。使用命令行参数可以指定分隔符、文件格式、压缩以及对导入过程进行更细粒度的控制。
1.2、生成代码
除了能够将数据库表的内容写到HDFS,Sqoop还生成了一个Java源文件(example.java)保存在当前的本地目录中。在运行了前面的sqoop import命令之后,可以通过ls example.java命令看到这个文件。代码生成时Sqoop导入过程的必要组成部分,他是在Sqoop将源数据库的表数据写到HDFS之前,首先用生成的代码对其进行反序列化。
生成的类中能够保存一条从被导入表中取出的记录。该类可以在MapReduce中使用这条记录,也可以将这条记录保存在HDFS中的一个SequenceFile文件中。在导入过程中,由Sqoop生成的SequenceFile文件会生成的类,将每一个被导入的行保存在其键值对格式中“值”的位置。
也许你不想将生成的类命名为example,因为每一个类的实例只对应与一条记录。我们可以使用另外一个Sqoop工具来生成源代码,并不执行导入操作,这个生成的代码仍然会检查数据库表,以确定与每个字段相匹配的数据类型:
Sqoop codegen –connect jdbc:mysql://localhost/yidong –table example –class-name example
Codegen工具只是简单的生成代码,他不执行完整的导入操作。我们指定希望生成一个名为example的类,这个类将被写入到example.java文件中。在之前执行的导入过程中,我们还可以指定—class-name和其他代码生成参数。如果你意外的删除了生成的源代码,或希望使用不同于导入过程的设定来生成代码,都可以用这个工具来重新生成代码。
如果计划使用导入到SequenceFile文件中的记录,你将不可避免的用到生成的类(对SequenceFile文件中的数据进行反序列化)。在使用文本文件中的记录时,不需要用生成的代码。
1.3、深入了解数据库导入
在深入理解之前,我们需要先想一个问题:Sqoop是通过一个MapReduce作业从数据库中导入一个表,这个作业从表中抽取一行行记录,然后写入到HDFS。MapReduce是如何记录的?
下图是Sqoop从数据库中导入到HDFS的原理图:
在导入开始之前,Sqoop使用JDBC来检查将要导入的表。他检索出表中所有的列以及列的SQL数据类型。这些SQL类型(VARCHAR、INTEGER)被映射到Java数据类型(String、Integer等),在MapReduce应用中将使用这些对应的java类型来保存字段的值。Sqoop的代码生成器使用这些信息来创建对应表的类,用于保存从表中抽取的记录。例如前面提到过的example类。
对于导入来说,更关键的是DBWritable接口的序列化方法,这些方法能使Widget类和JDBC进行交互:
Public void readFields(resultSet _dbResults)throws SQLException;
Public void write(PreparedStatement _dbstmt)throws SQLException;
JDBC的ResultSet接口提供了一个用户从检查结果中检索记录的游标;这里的readFields()方法将用ResultSet中一行数据的列来填充Example对象的字段。
Sqoop启动的MapReduce作业用到一个InputFormat,他可以通过JDBC从一个数据库表中读取部分内容。Hadoop提供的DataDriverDBInputFormat能够为几个Map任务对查询结果进行划分。为了获取更好的导入性能,查询会根据一个“划分列”来进行划分的。Sqoop会选择一个合适的列作为划分列(通常是表的主键)。
在生成反序列化代码和配置InputFormat之后,Sqoop将作业发送到MapReduce集群。Map任务将执行查询并将ResultSet中的数据反序列化到生成类的实例,这些数据要么直接保存在SequenceFile文件中,要么在写到HDFS之前被转换成分割的文本。
Sqoop不需要每次都导入整张表,用户也可以在查询中加入到where子句,以此来限定需要导入的记录:Sqoop –query 。
导入和一致性:在向HDFS导入数据时,重要的是要确保访问的是数据源的一致性快照。从一个数据库中并行读取数据的MAP任务分别运行在不同的进程中。因此,他们不能共享一个数据库任务。保证一致性的最好方法就是在导入时不允许运行任何进行对表中现有数据进行更新。
1.4、使用导入的数据
一旦数据导入HDFS,就可以供定制的MapReduce程序使用。导入的文本格式数据可以供Hadoop Streaming中的脚本或者TextInputFormat为默认格式运行的MapReduce作业使用。
为了使用导入记录的个别字段,必须对字段分割符进行解析,抽取出的字段值并转换为相应的数据类型。Sqoop生成的表类能自动完成这个过程,使你可以将精力集中在真正的要运行的MapReduce作业上。
1.5、导入的数据与hive
Hive和sqoop共同构成一个强大的服务于分析任务的工具链。Sqoop能够根据一个关系数据源中的表来生成一个hive表。既然我们已经将表的数据导入到HDFS中,那么就可以直接生成相应hive表的定义,然后加载保存在HDFS中的数据,例如:
Sqoop create-hive-table –connect jdbc:mysql://loca