Hadoop,MapReduce操作Mysql

來源:互聯網
上載者:User

標籤:style   blog   http   color   使用   os   io   檔案   

轉自:http://www.cnblogs.com/liqizhou/archive/2012/05/16/2503458.html

前以前文章介紹,怎樣讀取文本資料來源和多個資料來源的合并:http://www.cnblogs.com/liqizhou/archive/2012/05/15/2501835.html

這一個部落格介紹一下MapReduce怎樣讀取關聯式資料庫的資料,選擇的關聯式資料庫為MySql,因為它是開源的軟體,所以大家用的比較多。以前上學的時候就沒有用過開源的軟體,直接用盜版,也相當與免費,且比開源好用,例如向oracle,windows7等等。現在工作了,由於公司考慮成本的問題,所以都用成開源的,ubuntu,mysql等,本人現在支援開源,特別像hadoop這樣的東西,真的太好了,不但可以使用軟體,也可以讀到原始碼。話不說多了。

hadoop技術推出一首曾遭到關聯式資料庫研究者的挑釁和批評,認為MapReduce不具有關聯式資料庫中的結構化資料存放區和處理能力。為此,hadoop社區和研究人員做了多的努力,在hadoop0.19版支援MapReduce訪問關聯式資料庫,如:mysql,MySQL、PostgreSQL、Oracle 等幾個資料庫系統。

1. 從Mysql讀出資料

Hadoop訪問關聯式資料庫主要通過一下介面實現的:DBInputFormat類,包所在位置:org.apache.hadoop.mapred.lib.db 中。DBInputFormat 在 Hadoop 應用程式中通過資料庫供應商提供的 JDBC介面來與資料庫進行互動,並且可以使用標準的 SQL 來讀取資料庫中的記錄。學習DBInputFormat首先必須知道二個條件。

  1. 在使用 DBInputFormat 之前,必須將要使用的 JDBC 驅動拷貝到分布式系統各個節點的$HADOOP_HOME/lib/目錄下。

  2. MapReduce訪問關聯式資料庫時,大量頻繁的從MapReduce程式中查詢和讀取資料,這大大的增加了資料庫的訪問負載,因此,DBInputFormat介面僅僅適合讀取小資料量的資料,而不適合處理資料倉儲。要處理資料倉儲的方法有:利用資料庫的Dump工具將大量待分析的資料輸出為文本,並上傳的Hdfs中進行處理,處理的方法可參考:http://www.cnblogs.com/liqizhou/archive/2012/05/15/2501835.html

 

 DBInputFormat 類中包含以下三個內建類

  1. protected class DBRecordReader implementsRecordReader<LongWritable, T>:用來從一張資料庫表中讀取一條條元組記錄。

  2. 2.public static class NullDBWritable implements DBWritable,Writable:主要用來實現 DBWritable 介面。DBWritable介面要實現二個函數,第一是write,第二是readFileds,這二個函數都不難理解,一個是寫,一個是讀出所有欄位。原型如下:

    public void write(PreparedStatement statement) throwsSQLException;public void readFields(ResultSet resultSet) throws SQLException;
  3. protected static class DBInputSplit implements InputSplit:主要用來描述輸入元組集合的範圍,包括 start 和 end 兩個屬性,start 用來表示第一條記錄的索引號,end 表示最後一條記錄的索引號.

下面對怎樣使用 DBInputFormat 讀取資料庫記錄進行詳細的介紹,具體步驟如下:

  1. DBConfiguration.configureDB (JobConf job, StringdriverClass, String dbUrl, String userName, String passwd)函數,配置JDBC 驅動,資料來源,以及資料庫訪問的使用者名稱和密碼。MySQL 資料庫的 JDBC 的驅動為“com.mysql.jdbc.Driver”,資料來源為“jdbc:mysql://localhost/testDB”,其中testDB為訪問的資料庫。useName一般為“root”,passwd是你資料庫的密碼。

  2. DBInputFormat.setInput(JobConf job, Class<?extends DBWritable> inputClass, String tableName, String conditions,String orderBy, String... fieldNames),這個方法的參數很容易看懂,inputClass實現DBWritable介面。,string tableName表名, conditions表示查詢的條件,orderby表示排序的條件,fieldNames是欄位,這相當與把sql語句拆分的結果。當然也可以用sql語句進行重載。etInput(JobConf job, Class<?extends DBWritable> inputClass, String inputQuery, StringinputCountQuery)。

  3. 編寫MapReduce函數,包括Mapper 類、Reducer 類、輸入輸出檔案格式等,然後調用JobClient.runJob(conf)。

上面講了理論,下面舉個例子:假設 MySQL 資料庫中有資料庫student,假設資料庫中的欄位有“id”,“name”,“gender","number"。

第一步要實現DBwrite和write資料介面。代碼如下:

        public class StudentRecord implements Writable, DBWritable{            int id;            String name;            String gender;            String number;            @Override        public void readFields(DataInput in) throws IOException {            // TODO Auto-generated method stub            this.id = in.readInt();            this.gender = Text.readString(in);            this.name = in.readString();            this.number = in.readString();        }            @Override        public void write(DataOutput out) throws IOException {            // TODO Auto-generated method stub            out.writeInt(this.id);            Text.writeString(out,this.name);            out.writeInt(this.gender);            out.writeInt(this.number);        }                        @Override        public void readFields(ResultSet result) throws SQLException {            // TODO Auto-generated method stub            this.id = result.getInt(1);            this.name = result.getString(2);            this.gender = result.getString(3);            this.number = result.getString(4);        }                        @Override        public void write(PreparedStatement stmt) throws SQLException{            // TODO Auto-generated method stub            stmt.setInt(1, this.id);            stmt.setString(2, this.name);            stmt.setString(3, this.gender);            stmt.setString(4, this.number);        }            @Override        public String toString() {            // TODO Auto-generated method stub            return new String(this.name + " " + this.gender + " " +this.number);        }

第二步,實現Map和Reduce類

    public class DBAccessMapper extends MapReduceBase implements            Mapper<LongWritable, TeacherRecord, LongWritable, Text> {        @Override        public void map(LongWritable key, TeacherRecord value,                OutputCollector<LongWritable, Text> collector, Reporter reporter)                throws IOException {            // TODO Auto-generated method stub            new collector.collect(new LongWritable(value.id), new Text(value                    .toString()));        }    }

第三步:主函數的實現,函數

public class DBAccessReader {    public static void main(String[] args) throws IOException {        JobConf conf = new JobConf(DBAccessReader.class);        conf.setOutputKeyClass(LongWritable.class);        conf.setOutputValueClass(Text.class);        conf.setInputFormat(DBInputFormat.class);        FileOutputFormat.setOutputPath(conf, new Path("dboutput"));        DBConfiguration.configureDB(conf,"com.mysql.jdbc.Driver",        "jdbc:mysql://localhost/school","root","123456");        String [] fields = {"id", "name", "gender", "number"};        DBInputFormat.setInput(conf, StudentRecord.class,"Student",null "id", fields);        conf.setMapperClass(DBAccessMapper.class);        conf.setReducerClass(IdentityReducer.class);        JobClient.runJob(conf);        }}

2.寫資料

 往往對於資料處理的結果的資料量一般不會太大,可能適合hadoop直接寫入資料庫中。hadoop提供了相應的資料庫直接輸出的計算髮結果。

  1. DBOutFormat: 提供資料庫寫入介面。

  2. DBRecordWriter:提供向資料庫中寫入的資料記錄的介面。

  3. DBConfiguration:提供資料庫配置和建立連結的介面。

DBOutFormat提供一個靜態方法setOutput(job,String table,String ...filedNames);該方法的參數很容易看懂。假設要插入一個Student的資料,其代碼為

    public static void main(String[] args) throws IOException {        Configuration conf = new Configuration();        JobConf conf = new JobConf();        conf.setOutputFormat(DBOutputFormat.class);        DBConfiguration.configureDB(conf,"com.mysql.jdbc.Driver",                "jdbc:mysql://localhost/school","root","123456");        DBOutputFormat.setOutput(conf,"Student", 456, "liqizhou", "man", "20004154578");        JobClient.runJob(conf);


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.