是否可以在Java中使用SQOOP从MySQL读取/写入Hadoop作业?

时间:2013-06-06 14:46:39

标签: java mysql hadoop sqoop cascading

我目前正在开发一个使用JDK1.7编译的项目,使用Cascading 1.2(即将升级到2.1)创建并运行Hadoop作业,并使用Hadoop的Cloudera发行版(0.20.2-cdh3u3)。

我正在研究如何修改我的Cascading / Hadoop作业以读取和写入MySQL数据库的所有数据。看起来SQOOP可能能够解决这个问题。

然而,从我到目前为止所看到的,关于如何在Java中执行此操作的信息或文档很少(我知道SQOOP主要用于从shell中调用的批处理作业) - 我有Java示例其次没有为我工作。我已经尝试使用SQOOP 1.4并将我的项目切换为使用JDK1.6,因为我认为这是必需的,(虽然它会破坏我项目的其他部分)但我仍然无法使其工作。

有谁知道我想要实现的目标是否可行?其他人如何处理这个问题? SQOOP2的发布会有所帮助吗?

当我尝试运行org.apache.sqoop.tool.ExportTool以将CSV导出到表时,我看到的错误类型是:

由于(很可能)类加载器问题,无法初始化javac处理器:java.lang.NoClassDefFoundError:com / sun / tools / javac / processing / JavacProcessingEnvironment

注意:\ tmp \ sqoop-my.name \ compile \ 9031edc8e43167c10f9f895b64aa79d5 \ MyTableName.java使用或覆盖不推荐使用的API。

运行导出作业遇到IOException:java.io.IOException:无法将jar \ tmp \ sqoop-my.name \ compile \ 9031edc8e43167c10f9f895b64aa79d5 \ MyTableName.jar加载到JVM中。 (找不到类MyTableName。)

3 个答案:

答案 0 :(得分:2)

Sqoop用于在MySQL /其他关系数据库和Hadoop / HBase之间导出/导入数据。可以找到关于sqoop的非常好的教程here,它解释了它的各种功能。不确定这是否是你想要做的。

如果您需要在MapReduce作业中从/向MySQL读取/写入数据,可以按照@Charles的建议使用DBInputFormat/DBOutput hadoop类

答案 1 :(得分:1)

如果您只想将作业输出写入MySQL,我建议使用here所述的名为DBOutputFormat的其他输出格式:

  

伴侣类DBOutputFormat将允许您将结果写回数据库。设置作业时,请调用conf.setOutputFormat(DBOutputFormat.class);然后像以前一样调用DBConfiguration.configureDB()。

     

然后,DBOutputFormat.setOutput()方法定义如何将结果写回数据库。它的三个参数是作业的JobConf对象,一个定义要写入的表名称的字符串,以及一个字符串数组,用于定义要填充的表的字段。例如,DBOutputFormat.setOutput(job,“employees”,“employee_id”,“name”);.

     

您之前创建的相同DBWritable实现足以将记录注入数据库。将在从reducer传递给OutputCollector的DBWritable的每个实例上调用write(PreparedStatement stmt)方法。在还原结束时,那些PreparedStatement对象将转换为INSERT语句以对SQL数据库运行。

“如前所述”指的是这条指令:

DBConfiguration.configureDB(conf, “com.mysql.jdbc.Driver”, “jdbc:mysql://localhost/mydatabase”);

要从MySQL读取它与DBInputFormat完全相同。

答案 2 :(得分:1)

感谢Charles和Vikas。这当然让我走上正轨。我最终使用https://github.com/cwensel/cascading.jdbc使用Hadoop类DBInputFormat/DBOutput来轻松设置读写db的Cascading作业。

要写,我只是将我的点击输出流程更改为:

String url = "jdbc:mysql://localhost:3306/mydb?user=myusername&password=mypassword";
String driver = "com.mysql.jdbc.Driver";
String tableName = "mytable";   
String[] columnNames = {'col1', 'col2', 'col3'}; //Columns I want to write to 
TableDesc tableDesc = new TableDesc( tableName );

JDBCScheme dbScheme = new JDBCScheme( columnNames );
Tap dbOutputTap = new JDBCTap( url, driver, tableDesc, dbScheme );

要从数据库中读取,我只是做了一个看起来像这样的点击:

String url = "jdbc:mysql://localhost:3306/mydb?user=myusername&password=mypassword";
String driver = "com.mysql.jdbc.Driver";
String tableName = "mytable";      
String[] columnNames = {'col1', 'col2', 'col3'}; //Columns I want to read from 
TableDesc tableDesc = new TableDesc( tableName );

JDBCScheme dbScheme = new JDBCScheme( columnNames, "col1<40" );
Tap dbInputTap = new JDBCTap( url, driver, tableDesc, dbScheme );

我也遇到了Cascading-DBMigrate,但似乎这只是从db中读取而不是写入它们。