最近在做执行服务器,它根据用户输入的sqoop命令代理向hadoop提交任务执行,目前需要支持的数据源包括mysql、oracle以及公司自己的分布式数据库DDB,数据导入的目的地可以是HDFS或者hive表。
首先来讨论一下对hive的支持,hive是作为一个支持JDBC的数据库,它的数据分成两部分,元数据和数据,元数据保存在一个本地的数据库,例如嵌入式数据库derby或者mysql,主要是存储一些关于hive的数据库和表定义的一些信息(关于元数据库表需要补充一下,这些表的创建都是hive完成的,不需要我们预先创建,但是在mysql中需要将字符集设置为latin1,否则在hive操作的时候可能出现问题,参见
http://www.cnblogs.com/blueren/archive/2011/06/29/sir_001.html),数据保存在hadoop中,它支持将本地文件导入到hive中,其实hive在导入数据库的时候并不会解析数据库,而是是将文件存储在hadoop中,对于数据的来源,它只支持load这样的全量导入和批量导入的操作,并不支持一条条的insert操作和update操作,对hive的查询是利用hadoop的计算能力将select语句转换成一个或者多个hadoop任务,通过hadoop的计算得到SQL的执行结果。所以对于sqoop来说,导入到hive其实也是将数据导入到HDFS中,只不过hive需要对元数据进行操作,在sqoop中,导入数据到hive执行的操作和导入数据到HDFS大体上流程是差不多的,只不过导入到HDFS中是向hadoop提交一个job执行数据导入到HDFS的某个文件,而导入到hive的时候在将数据放到HDFS之后在生成一个hive的脚本,然后调用hive程序(或者直接调用命令行中的hive命令)使用"-f"参数来执行该文件,例如我将一个mysql中的表pf_sqoop导入到hive中的demo_blog_4表中,当前的hadoop用户是hive用户,该用户是代理intern用户执行的操作,生成的hive的脚本文件内容如下:
CREATE TABLE `demo_blog_4` ( `jobid` BIGINT, `product` STRING, `email` STRING, `jobname` STRING, `jobtype` TINYINT, `stype` TINYINT, `dtype` TINYINT, `dir` STRING, `dburl` STRING, `tablename` STRING, `username` STRING, `password` STRING, `hdbname` STRING, `htable` STRING, `params` STRING, `cluster` STRING, `begin_time` BIGINT, `end_time` BIGINT, `duration` BIGINT, `status` TINYINT, `created_at` STRING, `updated_at` STRING) COMMENT 'Imported by sqoop on 2015/04/13 10:16:31' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\001' LINES TERMINATED BY '\012' STORED AS TEXTFILE;
LOAD DATA INPATH 'hdfs://hp1/user/intern/pf_sqoop' OVERWRITE INTO TABLE `demo_blog_4`;<span style="font-family: Tahoma; background-color: rgb(255, 255, 255);"> </span>
可以看出,我们的数据库表的数据已经导入到HDFS的hdfs://hp1/user/intern/pf_sqoop路径下(这应该是/user/user_name/表名),然后执行创建hive表,再将该文件的数据导入到hive中,这里导入到hive表中是将已经存在hdfs中的文件再导入到hive的数据目录下。sqoop关于hive的参数有以下几个:
--create-hive-table //是否创建新表,覆盖原来的表定义
--hive-overwrite //是否覆盖hive中已经存在的数据
--hive-import //标记是否导入数据到hive
--hive-home //hive的主目录,必要的时候需要根据该配置找到hive命令
--hive-table //执行hive的表名
接下来看一下导入数据到HDFS吧,首先我们使用sqoop来执行mysql和HDFS之间的导入和导出,sqoop对于mysql的支持还是比较好的,实验一下就能够成功了,使用的命令如下:
sqoop import --table pf_sqoop --target-dir /user/intern/terry --delete-target-dir -m 1 --connect jdbc:mysql://ip:port/database?user=name\&password=passwd --input-fields-terminated-by ',',执行成功之后该目录/user/intern/terry下会创建导入的表数据的文件。--delete-target-dir参数意味着在生成数据之前将目标路径清空,也就意味着会覆盖之前的数据。