搜尋
首頁資料庫mysql教程Hadoop MapRduce 重写DBOutputFormat更新mysql数据库_MySQL

 

在http://blog.csdn.net/sunflower_cao/article/details/28266939  写过可以通过继承 Writable, DBWritable实现在reduce过程中讲结果写入到mysql数据库里边,但是一直有一个问题就是只能实现insert  没法去更新已经存在的数据,这就导致不同的mapreduce程序获得的数据只能插入到不同的数据库中 在使用的时候需要建立view或者使用复杂的sql语句去查询,今天调查了下,发现可以通过重写DBOutputFormat

 

上代码:

TblsWritable.java

import java.io.DataInput;import java.io.DataOutput;import java.io.IOException;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import org.apache.hadoop.io.Writable;import org.apache.hadoop.mapreduce.lib.db.DBWritable;/** * 重写DBWritable *  * @author caozw TblsWritable需要向mysql中写入数据 */public  class TblsWritable implements Writable, DBWritable {	String initTime;	String new_android_user;	String new_ios_user;	String new_total_user;	String iosUserTotal;	String androidUserTotal;	String userTotal;	public TblsWritable() {	}	public TblsWritable(String initTime, String new_android_user,			String new_ios_user, String new_total_user,			String iosUserTotal, String androidUserTotal, String userTotal) {		this.initTime = initTime;		this.new_android_user = new_android_user;		this.new_ios_user = new_ios_user;		this.new_total_user = new_total_user;		this.iosUserTotal = iosUserTotal;		this.androidUserTotal = androidUserTotal;		this.userTotal = userTotal;	}	@Override	public void write(PreparedStatement statement) throws SQLException {		statement.setString(1, this.new_android_user);		statement.setString(2, this.new_ios_user);		statement.setString(3, this.new_total_user);		statement.setString(4, this.androidUserTotal);		statement.setString(5, this.iosUserTotal);		statement.setString(6, this.userTotal);		statement.setString(7, this.initTime);	}	@Override	public void readFields(ResultSet resultSet) throws SQLException {		this.new_android_user = resultSet.getString(1);		this.new_ios_user = resultSet.getString(2);		this.new_total_user = resultSet.getString(3);		this.androidUserTotal = resultSet.getString(4);		this.iosUserTotal = resultSet.getString(5);		this.userTotal = resultSet.getString(6);		this.initTime = resultSet.getString(7);	}	@Override	public void write(DataOutput out) throws IOException {		out.writeUTF(this.new_android_user);		out.writeUTF(this.new_ios_user);		out.writeUTF(this.new_total_user);		out.writeUTF(this.androidUserTotal);		out.writeUTF(this.iosUserTotal);		out.writeUTF(this.userTotal);		out.writeUTF(this.initTime);	}	@Override	public void readFields(DataInput in) throws IOException {		this.new_android_user = in.readUTF();		this.new_ios_user = in.readUTF();		this.new_total_user = in.readUTF();		this.androidUserTotal = in.readUTF();		this.iosUserTotal = in.readUTF();		this.userTotal = in.readUTF();		this.initTime = in.readUTF();	}	public String toString() {		return new String(this.initTime + " " + this.new_android_user + " "				+ this.new_ios_user + " " + this.new_total_user + " "				+ this.androidUserTotal + " " + this.iosUserTotal + " "				+ this.userTotal);	}}


WriteDataToMysql.java

import java.io.IOException;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Iterator;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.fs.Path;import org.apache.hadoop.io.IntWritable;import org.apache.hadoop.io.LongWritable;import org.apache.hadoop.io.Text;import org.apache.hadoop.mapreduce.Job;import org.apache.hadoop.mapreduce.Mapper;import org.apache.hadoop.mapreduce.Reducer;import org.apache.hadoop.mapreduce.lib.db.DBConfiguration;import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;/** * 将mapreduce的结果数据写入mysql中 *  * @author caozw */public class WriteDataToMysql {	public static String[] fieldNames = { "INITTIME", "NEW_ANDROID_USER",			"NEW_IOS_USER", "NEW_USER_TOTAL", "TOTAL_ANDROID_USER",			"TOTAL_IOS_USER", "TOTAL_USER" };	public static String table = "USER_INFO_STATIC";		public static class ConnMysqlMapper extends			Mapper<longwritable text intwritable> {		enum Counter {			LINESKIP,		}		private final static IntWritable one = new IntWritable(1);		private final static IntWritable zero = new IntWritable(0);		public void map(LongWritable key, Text value, Context context)				throws IOException, InterruptedException {			try {				String line = value.toString();				String[] strings = line.split("/t");				String initTime = strings[1];				String devType = strings[4];				if (initTime.length() == 19) {					SimpleDateFormat sdf = new SimpleDateFormat(							"yyyy-MM-dd HH:mm:ss");					Date date = sdf.parse(initTime);					if ("1".equals(devType)) {						context.write(new Text(initTime.substring(0, 10)), one);						context.write(new Text(initTime.substring(0, 10)), zero);					}				} else {					// System.err.println(initTime);					context.getCounter(Counter.LINESKIP).increment(1);				}				// } catch (ArrayIndexOutOfBoundsException e) {			} catch (ArrayIndexOutOfBoundsException e) {				context.getCounter(Counter.LINESKIP).increment(1);				return;			} catch (ParseException e) {				context.getCounter(Counter.LINESKIP).increment(1);				return;			}		}	}	public static class ConnMysqlReducer extends			Reducer<text intwritable tblswritable> {		static int iosUserTotal = 0;		static int androidUserTotal = 0;		public void reduce(Text key, Iterable<intwritable> values,				Context context) throws IOException, InterruptedException {			int android = 0;			int ios = 0;			int total = 0;			for (Iterator<intwritable> itr = values.iterator(); itr.hasNext();) {				total++;				if (0 == itr.next().get()) {					android++;				} else {					ios++;				}			}			iosUserTotal += ios;			androidUserTotal += android;			/*			 * System.err.println(key.toString() + ":" + String.valueOf(android)			 * + ":" + String.valueOf(ios) + ":" + String.valueOf(total));			 */			context.write(					new TblsWritable(key.toString(), String.valueOf(android),							String.valueOf(ios), String.valueOf(total), String									.valueOf(androidUserTotal), String									.valueOf(iosUserTotal), String									.valueOf(androidUserTotal + iosUserTotal)),					null);		}	}	public static void main(String args[]) throws IOException,			InterruptedException, ClassNotFoundException {		Configuration conf = new Configuration();		DBConfiguration.configureDB(conf, "com.mysql.jdbc.Driver",				"jdbc:mysql://127.0.0.1:3306/XINGXUNTONG", "hadoop", "123456");		Job job = new Job(conf, "test mysql connection");		job.setJarByClass(WriteDataToMysql.class);		job.setMapperClass(ConnMysqlMapper.class);		job.setReducerClass(ConnMysqlReducer.class);		job.setOutputKeyClass(Text.class);		job.setOutputValueClass(IntWritable.class);		job.setSpeculativeExecution(false);		job.setInputFormatClass(TextInputFormat.class);		job.setOutputFormatClass(MysqlDBOutputFormat.class);		//job.setOutputFormatClass(DBOutputFormat.class);				FileInputFormat.addInputPath(job, new Path(args[0]));		// DBOutputFormat.setOutput(job, "test", "initTime", "new_user_total");		//DBOutputFormat.setOutput(job, table, fieldNames);		MysqlDBOutputFormat.setOutput(job, table, fieldNames);		System.exit(job.waitForCompletion(true) ? 0 : 1);	}}</intwritable></intwritable></text></longwritable>


MysqlDBOutputFormat.java

/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements.  See the NOTICE file * distributed with this work for additional information * regarding copyright ownership.  The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */import java.io.IOException;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.hadoop.classification.InterfaceAudience;import org.apache.hadoop.classification.InterfaceStability;import org.apache.hadoop.mapreduce.Job;import org.apache.hadoop.mapreduce.JobContext;import org.apache.hadoop.mapreduce.OutputCommitter;import org.apache.hadoop.mapreduce.OutputFormat;import org.apache.hadoop.mapreduce.RecordWriter;import org.apache.hadoop.mapreduce.TaskAttemptContext;import org.apache.hadoop.mapreduce.lib.db.DBConfiguration;import org.apache.hadoop.mapreduce.lib.db.DBWritable;import org.apache.hadoop.mapreduce.lib.output.FileOutputCommitter;import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;import org.apache.hadoop.util.StringUtils;/** * A OutputFormat that sends the reduce output to a SQL table. * <p>  * {@link MysqlDBOutputFormat} accepts <key> pairs, where  * key has a type extending DBWritable. Returned {@link RecordWriter}  * writes <b>only the key</b> to the database with a batch SQL query.   *  */@InterfaceAudience.Public@InterfaceStability.Stablepublic class MysqlDBOutputFormat<k extends dbwritable v> extends OutputFormat<k> {  private static final Log LOG = LogFactory.getLog(MysqlDBOutputFormat.class);  public void checkOutputSpecs(JobContext context)       throws IOException, InterruptedException {}  public OutputCommitter getOutputCommitter(TaskAttemptContext context)       throws IOException, InterruptedException {    return new FileOutputCommitter(FileOutputFormat.getOutputPath(context),                                   context);  }  /**   * A RecordWriter that writes the reduce output to a SQL table   */  @InterfaceStability.Evolving  public class DBRecordWriter       extends RecordWriter<k v> {    private Connection connection;    private PreparedStatement statement;    public DBRecordWriter() throws SQLException {    }    public DBRecordWriter(Connection connection        , PreparedStatement statement) throws SQLException {      this.connection = connection;      this.statement = statement;      this.connection.setAutoCommit(false);    }    public Connection getConnection() {      return connection;    }        public PreparedStatement getStatement() {      return statement;    }        /** {@inheritDoc} */    public void close(TaskAttemptContext context) throws IOException {      try {        statement.executeBatch();        connection.commit();      } catch (SQLException e) {        try {          connection.rollback();        }        catch (SQLException ex) {          LOG.warn(StringUtils.stringifyException(ex));        }        throw new IOException(e.getMessage());      } finally {        try {          statement.close();          connection.close();        }        catch (SQLException ex) {          throw new IOException(ex.getMessage());        }      }    }    /** {@inheritDoc} */    public void write(K key, V value) throws IOException {      try {        key.write(statement);        statement.addBatch();      } catch (SQLException e) {        e.printStackTrace();      }    }  }  /**   * Constructs the query used as the prepared statement to insert data.   *    * @param table   *          the table to insert into   * @param fieldNames   *          the fields to insert into. If field names are unknown, supply an   *          array of nulls.   */  public String constructQuery(String table, String[] fieldNames) {		if (fieldNames == null) {			throw new IllegalArgumentException(					"Field names may not be null");		}		StringBuilder query = new StringBuilder();		query.append("UPDATE ").append(table);		System.err.println("fieldNames.length:" + fieldNames.length);		if (fieldNames.length > 0) {			query.append(" SET ");			query.append(fieldNames[1] + " = ?");			query.append("," + fieldNames[2] + " = ?");			query.append("," + fieldNames[3] + " = ?");			query.append("," + fieldNames[4] + " = ?");			query.append("," + fieldNames[5] + " = ?");			query.append("," + fieldNames[6] + " = ?");			query.append(" WHERE ");			query.append(fieldNames[0] + " = ?");			System.err.println(query.toString());			return query.toString();		} else {			return null;		}  }  /** {@inheritDoc} */  public RecordWriter<k v> getRecordWriter(TaskAttemptContext context)       throws IOException {    DBConfiguration dbConf = new DBConfiguration(context.getConfiguration());    String tableName = dbConf.getOutputTableName();    String[] fieldNames = dbConf.getOutputFieldNames();        if(fieldNames == null) {      fieldNames = new String[dbConf.getOutputFieldCount()];    }        try {      Connection connection = dbConf.getConnection();      PreparedStatement statement = null;        statement = connection.prepareStatement(                    constructQuery(tableName, fieldNames));      return new DBRecordWriter(connection, statement);    } catch (Exception ex) {      throw new IOException(ex.getMessage());    }  }  /**   * Initializes the reduce-part of the job with    * the appropriate output settings   *    * @param job The job   * @param tableName The table to insert data into   * @param fieldNames The field names in the table.   */  public static void setOutput(Job job, String tableName,       String... fieldNames) throws IOException {    if(fieldNames.length > 0 && fieldNames[0] != null) {      DBConfiguration dbConf = setOutput(job, tableName);      dbConf.setOutputFieldNames(fieldNames);    } else {      if (fieldNames.length > 0) {        setOutput(job, tableName, fieldNames.length);      }      else {         throw new IllegalArgumentException(          "Field names must be greater than 0");      }    }  }    /**   * Initializes the reduce-part of the job    * with the appropriate output settings   *    * @param job The job   * @param tableName The table to insert data into   * @param fieldCount the number of fields in the table.   */  public static void setOutput(Job job, String tableName,       int fieldCount) throws IOException {    DBConfiguration dbConf = setOutput(job, tableName);    dbConf.setOutputFieldCount(fieldCount);  }    private static DBConfiguration setOutput(Job job,      String tableName) throws IOException {    job.setOutputFormatClass(MysqlDBOutputFormat.class);    job.setReduceSpeculativeExecution(false);    DBConfiguration dbConf = new DBConfiguration(job.getConfiguration());        dbConf.setOutputTableName(tableName);    return dbConf;  }}</k></k></k></k></key></p>


MysqlDBOutputFormat.java是将hadoop源码里边的DBOutputFormat.java拿过来重写了里边的constructQuery的方法,在生成sql语句的时候产生update的sql语句来实现的

DBOutputFormat.java里边的constructQuery

public String constructQuery(String table, String[] fieldNames) {    if(fieldNames == null) {      throw new IllegalArgumentException("Field names may not be null");    }    StringBuilder query = new StringBuilder();    query.append("INSERT INTO ").append(table);    if (fieldNames.length > 0 && fieldNames[0] != null) {      query.append(" (");      for (int i = 0; i <p><br>重写后:</p><pre class="brush:php;toolbar:false">public String constructQuery(String table, String[] fieldNames) {		if (fieldNames == null) {			throw new IllegalArgumentException(					"Field names may not be null");		}		StringBuilder query = new StringBuilder();		query.append("UPDATE ").append(table);		System.err.println("fieldNames.length:" + fieldNames.length);		if (fieldNames.length > 0) {			query.append(" SET ");			query.append(fieldNames[1] + " = ?");			query.append("," + fieldNames[2] + " = ?");			query.append("," + fieldNames[3] + " = ?");			query.append("," + fieldNames[4] + " = ?");			query.append("," + fieldNames[5] + " = ?");			query.append("," + fieldNames[6] + " = ?");			query.append(" WHERE ");			query.append(fieldNames[0] + " = ?");			System.err.println(query.toString());			return query.toString();		} else {			return null;		}  }


按照java的思想我这里其实可以通过extends DBOutputFomat来实现update mysql的功能 ,但是我试了死活不行,暂且记下 有时间再来仔细揣摩

重载方式代码(测试未通过)有知道为什么的还请不吝赐教

import org.apache.hadoop.mapreduce.lib.db.DBOutputFormat;import org.apache.hadoop.mapreduce.lib.db.DBWritable;public class MysqlOutputFormat1<k extends dbwritable> extends DBOutputFormat<k v> {	public String constructQuery(String table, String[] fieldNames) {		if (fieldNames == null) {			throw new IllegalArgumentException(					"Field names may not be null");		}		StringBuilder query = new StringBuilder();		query.append("UPDATE ").append(table);		System.err.println("fieldNames.length:"+fieldNames.length);		if (fieldNames.length > 0) {			query.append(" SET ");			query.append(fieldNames[1] + " = ?");			query.append("," + fieldNames[2] + " = ?");			query.append("," + fieldNames[3] + " = ?");			query.append("," + fieldNames[4] + " = ?");			query.append("," + fieldNames[5] + " = ?");			query.append("," + fieldNames[6] + " = ?");			query.append(" WHERE ");			query.append(fieldNames[0] + " = ?");			System.err.println(query.toString());			return query.toString();		} else {			return null;		}	}}</k></k>


另外可以通过我感觉可以通过sql语句的merge方式生成merge语句从而实现有则更新 没有则插入 参考网页http://en.wikipedia.org/wiki/Merge_%28SQL%29

--http://en.wikipedia.org/wiki/Merge_%28SQL%29 MERGE INTO tablename USING table_reference ON (condition)   WHEN MATCHED THEN   UPDATE SET column1 = value1 [, column2 = value2 ...]   WHEN NOT MATCHED THEN   INSERT (column1 [, column2 ...]) VALUES (value1 [, value2 ...


 

 

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
解釋InnoDB緩衝池及其對性能的重要性。解釋InnoDB緩衝池及其對性能的重要性。Apr 19, 2025 am 12:24 AM

InnoDBBufferPool通過緩存數據和索引頁來減少磁盤I/O,提升數據庫性能。其工作原理包括:1.數據讀取:從BufferPool中讀取數據;2.數據寫入:修改數據後寫入BufferPool並定期刷新到磁盤;3.緩存管理:使用LRU算法管理緩存頁;4.預讀機制:提前加載相鄰數據頁。通過調整BufferPool大小和使用多個實例,可以優化數據庫性能。

MySQL與其他編程語言:一種比較MySQL與其他編程語言:一種比較Apr 19, 2025 am 12:22 AM

MySQL与其他编程语言相比,主要用于存储和管理数据,而其他语言如Python、Java、C 则用于逻辑处理和应用开发。MySQL以其高性能、可扩展性和跨平台支持著称,适合数据管理需求,而其他语言在各自领域如数据分析、企业应用和系统编程中各有优势。

學習MySQL:新用戶的分步指南學習MySQL:新用戶的分步指南Apr 19, 2025 am 12:19 AM

MySQL值得學習,因為它是強大的開源數據庫管理系統,適用於數據存儲、管理和分析。 1)MySQL是關係型數據庫,使用SQL操作數據,適合結構化數據管理。 2)SQL語言是與MySQL交互的關鍵,支持CRUD操作。 3)MySQL的工作原理包括客戶端/服務器架構、存儲引擎和查詢優化器。 4)基本用法包括創建數據庫和表,高級用法涉及使用JOIN連接表。 5)常見錯誤包括語法錯誤和權限問題,調試技巧包括檢查語法和使用EXPLAIN命令。 6)性能優化涉及使用索引、優化SQL語句和定期維護數據庫。

MySQL:初學者的基本技能MySQL:初學者的基本技能Apr 18, 2025 am 12:24 AM

MySQL適合初學者學習數據庫技能。 1.安裝MySQL服務器和客戶端工具。 2.理解基本SQL查詢,如SELECT。 3.掌握數據操作:創建表、插入、更新、刪除數據。 4.學習高級技巧:子查詢和窗口函數。 5.調試和優化:檢查語法、使用索引、避免SELECT*,並使用LIMIT。

MySQL:結構化數據和關係數據庫MySQL:結構化數據和關係數據庫Apr 18, 2025 am 12:22 AM

MySQL通過表結構和SQL查詢高效管理結構化數據,並通過外鍵實現表間關係。 1.創建表時定義數據格式和類型。 2.使用外鍵建立表間關係。 3.通過索引和查詢優化提高性能。 4.定期備份和監控數據庫確保數據安全和性能優化。

MySQL:解釋的關鍵功能和功能MySQL:解釋的關鍵功能和功能Apr 18, 2025 am 12:17 AM

MySQL是一個開源的關係型數據庫管理系統,廣泛應用於Web開發。它的關鍵特性包括:1.支持多種存儲引擎,如InnoDB和MyISAM,適用於不同場景;2.提供主從復制功能,利於負載均衡和數據備份;3.通過查詢優化和索引使用提高查詢效率。

SQL的目的:與MySQL數據庫進行交互SQL的目的:與MySQL數據庫進行交互Apr 18, 2025 am 12:12 AM

SQL用於與MySQL數據庫交互,實現數據的增、刪、改、查及數據庫設計。 1)SQL通過SELECT、INSERT、UPDATE、DELETE語句進行數據操作;2)使用CREATE、ALTER、DROP語句進行數據庫設計和管理;3)複雜查詢和數據分析通過SQL實現,提升業務決策效率。

初學者的MySQL:開始數據庫管理初學者的MySQL:開始數據庫管理Apr 18, 2025 am 12:10 AM

MySQL的基本操作包括創建數據庫、表格,及使用SQL進行數據的CRUD操作。 1.創建數據庫:CREATEDATABASEmy_first_db;2.創建表格:CREATETABLEbooks(idINTAUTO_INCREMENTPRIMARYKEY,titleVARCHAR(100)NOTNULL,authorVARCHAR(100)NOTNULL,published_yearINT);3.插入數據:INSERTINTObooks(title,author,published_year)VA

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱工具

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

強大的PHP整合開發環境

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具