今天想通过一些数据,来测试一下我的《基于信息熵的无字典分词算法》这篇文章的正确性。就写了一下MapReduce程序从MSSQL SERVER2008数据库里取数据分析。程序发布到hadoop机器上运行报SQLEXCEPTION错误

  奇怪了,我的SQL语句中没有LIMIT,这LIMIT哪来的。我翻看了DBInputFormat类的源码,

  1. protected RecordReader<LongWritable, T> createDBRecordReader(DBInputSplit split,
  2.  
  3. Configuration conf) throws IOException {
  4.  
  5. @SuppressWarnings("unchecked")
  6.  
  7. Class<T> inputClass = (Class<T>) (dbConf.getInputClass());
  8.  
  9. try {
  10.  
  11. // use database product name to determine appropriate record reader.
  12.  
  13. if (dbProductName.startsWith("ORACLE")) {
  14.  
  15. // use Oracle-specific db reader.
  16.  
  17. return new OracleDBRecordReader<T>(split, inputClass,
  18.  
  19. conf, createConnection(), getDBConf(), conditions, fieldNames,
  20.  
  21. tableName);
  22.  
  23. } else if (dbProductName.startsWith("MYSQL")) {
  24.  
  25. // use MySQL-specific db reader.
  26.  
  27. return new MySQLDBRecordReader<T>(split, inputClass,
  28.  
  29. conf, createConnection(), getDBConf(), conditions, fieldNames,
  30.  
  31. tableName);
  32.  
  33. } else {
  34.  
  35. // Generic reader.
  36.  
  37. return new DBRecordReader<T>(split, inputClass,
  38.  
  39. conf, createConnection(), getDBConf(), conditions, fieldNames,
  40.  
  41. tableName);
  42.  
  43. }
  44.  
  45. } catch (SQLException ex) {
  46.  
  47. throw new IOException(ex.getMessage());
  48.  
  49. }
  50.  
  51. }

DBRecordReader的源码

  1. protected String getSelectQuery() {
  2.  
  3. StringBuilder query = new StringBuilder();
  4.  
  5. // Default codepath for MySQL, HSQLDB, etc. Relies on LIMIT/OFFSET for splits.
  6.  
  7. if(dbConf.getInputQuery() == null) {
  8.  
  9. query.append("SELECT ");
  10.  
  11. for (int i = 0; i < fieldNames.length; i++) {
  12.  
  13. query.append(fieldNames[i]);
  14.  
  15. if (i != fieldNames.length -1) {
  16.  
  17. query.append(", ");
  18.  
  19. }
  20.  
  21. }
  22.  
  23. query.append(" FROM ").append(tableName);
  24.  
  25. query.append(" AS ").append(tableName); //in hsqldb this is necessary
  26.  
  27. if (conditions != null && conditions.length() > 0) {
  28.  
  29. query.append(" WHERE (").append(conditions).append(")");
  30.  
  31. }
  32.  
  33. String orderBy = dbConf.getInputOrderBy();
  34.  
  35. if (orderBy != null && orderBy.length() > 0) {
  36.  
  37. query.append(" ORDER BY ").append(orderBy);
  38.  
  39. }
  40.  
  41. } else {
  42.  
  43. //PREBUILT QUERY
  44.  
  45. query.append(dbConf.getInputQuery());
  46.  
  47. }
  48.  
  49. try {
  50.  
  51. query.append(" LIMIT ").append(split.getLength()); //问题所在
  52.  
  53. query.append(" OFFSET ").append(split.getStart());
  54.  
  55. } catch (IOException ex) {
  56.  
  57. // Ignore, will not throw.
  58.  
  59. }
  60.  
  61. return query.toString();
  62.  
  63. }

终于找到原因了。

  原来,hadoop只实现了Mysql的DBRecordReader(MySQLDBRecordReader)和ORACLE的DBRecordReader(OracleDBRecordReader)。

原因找到了,我参考着OracleDBRecordReader实现了MSSQL SERVER的DBRecordReader代码如下:

  MSSQLDBInputFormat的代码:

  1. /**
  2. *
  3. */
  4. package org.apache.hadoop.mapreduce.lib.db;
  5.  
  6. import java.io.IOException;
  7. import java.sql.SQLException;
  8.  
  9. import org.apache.hadoop.conf.Configuration;
  10. import org.apache.hadoop.io.LongWritable;
  11. import org.apache.hadoop.mapreduce.Job;
  12. import org.apache.hadoop.mapreduce.RecordReader;
  13.  
  14. /**
  15. * @author summer
  16. * MICROSOFT SQL SERVER
  17. */
  18. public class MSSQLDBInputFormat<T extends DBWritable> extends DBInputFormat<T> {
  19.  
  20. public static void setInput(Job job,
  21. Class<? extends DBWritable> inputClass,
  22. String inputQuery, String inputCountQuery,String rowId) {
  23. job.setInputFormatClass(MSSQLDBInputFormat.class);
  24. DBConfiguration dbConf = new DBConfiguration(job.getConfiguration());
  25. dbConf.setInputClass(inputClass);
  26. dbConf.setInputQuery(inputQuery);
  27. dbConf.setInputCountQuery(inputCountQuery);
  28. dbConf.setInputFieldNames(new String[]{rowId});
  29. }
  30.  
  31. @Override
  32. protected RecordReader<LongWritable, T> createDBRecordReader(
  33. org.apache.hadoop.mapreduce.lib.db.DBInputFormat.DBInputSplit split,
  34. Configuration conf) throws IOException {
  35.  
  36. @SuppressWarnings("unchecked")
  37. Class<T> inputClass = (Class<T>) (dbConf.getInputClass());
  38. try {
  39.  
  40. return new MSSQLDBRecordReader<T>(split, inputClass,
  41. conf, createConnection(), getDBConf(), conditions, fieldNames,
  42. tableName);
  43.  
  44. } catch (SQLException ex) {
  45. throw new IOException(ex.getMessage());
  46. }
  47.  
  48. }
  49.  
  50. }

  MSSQLDBRecordReader的代码:

  1. /**
  2. *
  3. */
  4. package org.apache.hadoop.mapreduce.lib.db;
  5.  
  6. import java.io.IOException;
  7. import java.sql.Connection;
  8. import java.sql.SQLException;
  9.  
  10. import org.apache.hadoop.conf.Configuration;
  11.  
  12. /**
  13. * @author summer
  14. *
  15. */
  16. public class MSSQLDBRecordReader <T extends DBWritable> extends DBRecordReader<T>{
  17.  
  18. public MSSQLDBRecordReader(DBInputFormat.DBInputSplit split,
  19. Class<T> inputClass, Configuration conf, Connection conn, DBConfiguration dbConfig,
  20. String cond, String [] fields, String table) throws SQLException {
  21. super(split, inputClass, conf, conn, dbConfig, cond, fields, table);
  22.  
  23. }
  24.  
  25. @Override
  26. protected String getSelectQuery() {
  27. StringBuilder query = new StringBuilder();
  28. DBConfiguration dbConf = getDBConf();
  29. String conditions = getConditions();
  30. String tableName = getTableName();
  31. String [] fieldNames = getFieldNames();
  32.  
  33. // Oracle-specific codepath to use rownum instead of LIMIT/OFFSET.
  34. if(dbConf.getInputQuery() == null) {
  35. query.append("SELECT ");
  36.  
  37. for (int i = 0; i < fieldNames.length; i++) {
  38. query.append(fieldNames[i]);
  39. if (i != fieldNames.length -1) {
  40. query.append(", ");
  41. }
  42. }
  43.  
  44. query.append(" FROM ").append(tableName);
  45. if (conditions != null && conditions.length() > 0)
  46. query.append(" WHERE ").append(conditions);
  47. String orderBy = dbConf.getInputOrderBy();
  48. if (orderBy != null && orderBy.length() > 0) {
  49. query.append(" ORDER BY ").append(orderBy);
  50. }
  51. } else {
  52. //PREBUILT QUERY
  53. query.append(dbConf.getInputQuery());
  54. }
  55.  
  56. try {
  57. DBInputFormat.DBInputSplit split = getSplit();
  58. if (split.getLength() > 0){
  59. String querystring = query.toString();
  60. String id = fieldNames[0];
  61. query = new StringBuilder();
  62. query.append("SELECT TOP "+split.getLength()+"* FROM ( ");
  63. query.append(querystring);
  64. query.append(" ) a WHERE " + id +" NOT IN (SELECT TOP ").append(split.getEnd());
  65. query.append(" "+id +" FROM (");
  66. query.append(querystring);
  67. query.append(" ) b");
  68. query.append(" )");
  69. System.out.println("----------------------MICROSOFT SQL SERVER QUERY STRING---------------------------");
  70. System.out.println(query.toString());
  71. System.out.println("----------------------MICROSOFT SQL SERVER QUERY STRING---------------------------");
  72. }
  73. } catch (IOException ex) {
  74. // ignore, will not throw.
  75. }
  76.  
  77. return query.toString();
  78. }
  79.  
  80. }

mapreduce的代码

  1. /**
  2. *
  3. */
  4. package com.nltk.sns.mapreduce;
  5.  
  6. import java.io.IOException;
  7. import java.util.List;
  8.  
  9. import org.apache.hadoop.conf.Configuration;
  10. import org.apache.hadoop.fs.FileSystem;
  11. import org.apache.hadoop.fs.Path;
  12. import org.apache.hadoop.io.LongWritable;
  13. import org.apache.hadoop.io.Text;
  14. import org.apache.hadoop.mapreduce.Job;
  15. import org.apache.hadoop.mapreduce.MRJobConfig;
  16. import org.apache.hadoop.mapreduce.Mapper;
  17. import org.apache.hadoop.mapreduce.lib.db.DBConfiguration;
  18. import org.apache.hadoop.mapreduce.lib.db.MSSQLDBInputFormat;
  19. import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
  20.  
  21. import com.nltk.utils.ETLUtils;
  22.  
  23. /**
  24. * @author summer
  25. *
  26. */
  27. public class LawDataEtl {
  28.  
  29. public static class CaseETLMapper extends
  30. Mapper<LongWritable, LawCaseRecord, LongWritable, Text>{
  31.  
  32. static final int step = 6;
  33.  
  34. LongWritable key = new LongWritable(1);
  35. Text value = new Text();
  36.  
  37. @Override
  38. protected void map(
  39. LongWritable key,
  40. LawCaseRecord lawCaseRecord,
  41. Mapper<LongWritable, LawCaseRecord, LongWritable, Text>.Context context)
  42. throws IOException, InterruptedException {
  43.  
  44. System.out.println("-----------------------------"+lawCaseRecord+"------------------------------");
  45.  
  46. key.set(lawCaseRecord.id);
  47. String source = ETLUtils.format(lawCaseRecord.source);
  48. List<LawCaseWord> words = ETLUtils.split(lawCaseRecord.id,source, step);
  49. for(LawCaseWord w:words){
  50. value.set(w.toString());
  51. context.write(key, value);
  52. }
  53. }
  54. }
  55.  
  56. static final String driverClass = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
  57. static final String dbUrl = "jdbc:sqlserver://192.168.0.1:1433;DatabaseName=XXX";
  58. static final String uid = "XXX";
  59. static final String pwd = "XXX";
  60. static final String inputQuery = "select id,source from tablename where id<1000";
  61. static final String inputCountQuery = "select count(1) from LawDB.dbo.case_source where id<1000";
  62. static final String jarClassPath = "/user/lib/sqljdbc4.jar";
  63. static final String outputPath = "hdfs://ubuntu:9000/user/test";
  64. static final String rowId = "id";
  65.  
  66. public static Job configureJob(Configuration conf) throws Exception{
  67.  
  68. String jobName = "etlcase";
  69. Job job = Job.getInstance(conf, jobName);
  70.  
  71. job.addFileToClassPath(new Path(jarClassPath));
  72. MSSQLDBInputFormat.setInput(job, LawCaseRecord.class, inputQuery, inputCountQuery,rowId);
  73. job.setJarByClass(LawDataEtl.class);
  74.  
  75. FileOutputFormat.setOutputPath(job, new Path(outputPath));
  76.  
  77. job.setMapOutputKeyClass(LongWritable.class);
  78. job.setMapOutputValueClass(Text.class);
  79. job.setOutputKeyClass(LongWritable.class);
  80. job.setOutputValueClass(Text.class);
  81. job.setMapperClass(CaseETLMapper.class);
  82.  
  83. return job;
  84. }
  85.  
  86. public static void main(String[] args) throws Exception{
  87.  
  88. Configuration conf = new Configuration();
  89. FileSystem fs = FileSystem.get(conf);
  90. fs.delete(new Path(outputPath), true);
  91.  
  92. DBConfiguration.configureDB(conf, driverClass, dbUrl, uid, pwd);
  93. conf.set(MRJobConfig.NUM_MAPS, String.valueOf(10));
  94. Job job = configureJob(conf);
  95. System.out.println("------------------------------------------------");
  96. System.out.println(conf.get(DBConfiguration.DRIVER_CLASS_PROPERTY));
  97. System.out.println(conf.get(DBConfiguration.URL_PROPERTY));
  98. System.out.println(conf.get(DBConfiguration.USERNAME_PROPERTY));
  99. System.out.println(conf.get(DBConfiguration.PASSWORD_PROPERTY));
  100. System.out.println("------------------------------------------------");
  101. System.exit(job.waitForCompletion(true) ? 0 : 1);
  102.  
  103. }
  104. }

辅助类的代码:

  1. /**
  2. *
  3. */
  4. package com.nltk.sns;
  5.  
  6. import java.util.ArrayList;
  7. import java.util.List;
  8.  
  9. import org.apache.commons.lang.StringUtils;
  10.  
  11. /**
  12. * @author summer
  13. *
  14. */
  15. public class ETLUtils {
  16.  
  17. public final static String NULL_CHAR = "";
  18. public final static String PUNCTUATION_REGEX = "[(\\pP)&&[^\\|\\{\\}\\#]]+";
  19. public final static String WHITESPACE_REGEX = "[\\p{Space}]+";
  20.  
  21. public static String format(String s){
  22.  
  23. return s.replaceAll(PUNCTUATION_REGEX, NULL_CHAR).replaceAll(WHITESPACE_REGEX, NULL_CHAR);
  24. }
  25.  
  26. public static List<String> split(String s,int stepN){
  27.  
  28. List<String> splits = new ArrayList<String>();
  29. if(StringUtils.isEmpty(s) || stepN<1)
  30. return splits;
  31. int len = s.length();
  32. if(len<=stepN)
  33. splits.add(s);
  34. else{
  35. for(int j=1;j<=stepN;j++)
  36. for(int i=0;i<=len-j;i++){
  37. String key = StringUtils.mid(s, i,j);
  38. if(StringUtils.isEmpty(key))
  39. continue;
  40. splits.add(key);
  41. }
  42. }
  43. return splits;
  44.  
  45. }
  46.  
  47. public static void main(String[] args){
  48.  
  49. String s="谢婷婷等与姜波等";
  50. int stepN = 2;
  51. List<String> splits = split(s,stepN);
  52. System.out.println(splits);
  53. }
  54. }

运行成功了

代码初略的实现,主要是为了满足我的需求,大家可以根据自己的需要进行修改。

  实际上DBRecordReader作者实现的并不好,我们来看DBRecordReader、MySQLDBRecordReader和OracleDBRecordReader源码,DBRecordReader和MySQLDBRecordReader耦合度太高。一般而言,就是对于没有具体实现的数据库DBRecordReader也应该做到运行不报异常,无非就是采用单一的SPLIT和单一的MAP。

mapreduce导出MSSQL的数据到HDFS的更多相关文章

  1. 使用C#导出MSSQL表数据Insert语句,支持所有MSSQL列属性

    在正文开始之前,我们先看一下MSSQL的两张系统表sys.objects . syscolumnsMSDN中 sys.objects表的定义:在数据库中创建的每个用户定义的架构作用域内的对象在该表中均 ...

  2. MapReduce(十六): 写数据到HDFS的源代码分析

    1)   LineRecordWriter负责把Key,Value的形式把数据写入到DFSOutputStream watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZ ...

  3. 使用MapReduce将mysql数据导入HDFS

    package com.zhen.mysqlToHDFS; import java.io.DataInput; import java.io.DataOutput; import java.io.IO ...

  4. 1.6-1.10 使用Sqoop导入数据到HDFS及一些设置

    一.导数据 1.import和export Sqoop可以在HDFS/Hive和关系型数据库之间进行数据的导入导出,其中主要使用了import和export这两个工具.这两个工具非常强大, 提供了很多 ...

  5. BCP导入导出MsSql

    BCP导入导出MsSql 1.导出数据 (1).在Sql Server Management Studio中: --导出数据到tset1.txt,并指定本地数据库的用户名和密码 --这里需要指定数据库 ...

  6. sqoop将oracle数据导入hdfs集群

    使用sqoop将oracle数据导入hdfs集群 集群环境: hadoop1.0.0 hbase0.92.1 zookeeper3.4.3 hive0.8.1 sqoop-1.4.1-incubati ...

  7. 大数据(1)---大数据及HDFS简述

    一.大数据简述 在互联技术飞速发展过程中,越来越多的人融入互联网.也就意味着各个平台的用户所产生的数据也越来越多,可以说是爆炸式的增长,以前传统的数据处理的技术已经无法胜任了.比如淘宝,每天的活跃用户 ...

  8. 第3节 sqoop:4、sqoop的数据导入之导入数据到hdfs和导入数据到hive表

    注意: (1)\001 是hive当中默认使用的分隔符,这个玩意儿是一个asc 码值,键盘上面打不出来 (2)linux中一行写不下,可以末尾加上 一些空格和 “ \ ”,换行继续写余下的命令: bi ...

  9. 关于Java导出100万行数据到Excel的优化方案

    1>场景 项目中需要从数据库中导出100万行数据,以excel形式下载并且只要一张sheet(打开这么大文件有多慢另说,呵呵). ps:xlsx最大容纳1048576行 ,csv最大容纳1048 ...

随机推荐

  1. git开发流程、常用命令及工具、TortoiseGit使用及常见问题

    根据我最近使用git的一些经历,git是基于分支的版本控制工具,分支有远程分支和本地分支. 一.开发流程 - 从远程服务器的master,clone一份项目文件到本地,然后本地master的基础上br ...

  2. HashMap和HashTable到底哪不同?

    HashMap和HashTable有什么不同?在面试和被面试的过程中,我问过也被问过这个问题,也见过了不少回答,今天决定写一写自己心目中的理想答案. 代码版本 JDK每一版本都在改进.本文讨论的Has ...

  3. Linux(Centos)快速搭建SVN

    前言 项目中源码或者文档需要进行管理与版本记录,历数此类工具VSS.CVS.SVN.GIT等等,有非常多的版本控制系统.SVN现在还是很常见,把笔记总结搬上博客,SVN这个再不放以后估计只能写GIT的 ...

  4. OpenGL新手框架

    开始学习用OpenGL,也就想显示一些点,以为挺简单的,哎,看了两天才会画三维的点,做个总结. 使用OpenGL的基本流程 int main(int argv, char *argc[]) { //初 ...

  5. jQuery-1.9.1源码分析系列(三) Sizzle选择器引擎——词法解析

    jQuery源码9600多行,而Sizzle引擎就独占近2000行,占了1/5.Sizzle引擎.jQuery事件机制.ajax是整个jQuery的核心,也是jQuery技术精华的体现.里面的有些策略 ...

  6. Windows 10 内置管理员无法打开Metro应用方法

    前言 在windows 10中,由于权限原因,使用了内置管理员账户.虽然这样权限获取了,但是不能打开Metro应用,Microsoft Edge浏览器等,有点不太好.那有没有方法可以修改呢?这是本文要 ...

  7. Hibernate框架中Criteria语句

    在Hibernate中有一种查询语句是Criteria查询(QBC查询),今天呢 我们就一个个的详细的跟大家一起探讨Criteria语句的相关知识点 案例前的准备 //插入测试数据,构建数据库 pub ...

  8. C# DataGridView中指定的单元格不能编辑

    注意:DataGridView控件是从.NET Framework 2.0版本开始追加的. ReadOnly属性的使用 DataGridView内所有的单元格不能编辑 当DataGridView.Re ...

  9. entityframework学习笔记--004-无载荷与有载荷关系

    1.无载荷(with NO Payload)的多对多关系建模 在数据库中,存在通过一张链接表来关联两张表的情况.链接表仅包含连接两张表形成多对多关系的外键,你需要把这两张多对多关系的表导入到实体框架模 ...

  10. ASP对XML的增、删、改、查

    首先看一下xml文件 text.xml 'encoding使用gb2312中文,如果要用英文则用utf-8 <?xml version="1.0" encoding=&quo ...