1. 程式人生 > 實用技巧 >Hbase基礎(十八):億級資料從 MySQL 到 Hbase 的三種同步方案與實踐(二)億級MySQL資料插入

Hbase基礎(十八):億級資料從 MySQL 到 Hbase 的三種同步方案與實踐(二)億級MySQL資料插入

原文:https://blog.csdn.net/rlnlo2pnefx9c/article/details/108288956

本節題目為:億級資料從 MySQL 到 Hbase 的三種同步方案與實踐,首先需要了解如何快速插入MySQL。

那麼MySQL資料插入將會從以下幾個方法入手:

  • load data infile

  • Python 單條插入

  • Python 多執行緒插入

當然也可以使用其他語言進行實現!!!

下面來逐步談談資料插入!

資料插入之前,需要了解我們的資料,先來看一下資料欄位描述:

資料以ASCII文字表示,以逗號為分隔符,以回車換行符(0x0D 0x0A)結尾。資料項及順序:車輛標識、觸發事件、運營狀態、GPS時間、GPS經度、GPS緯度,、GPS速度、GPS方向、GPS狀態
車輛標識:6個字元
觸發事件:0
=變空車,1=變載客,2=設防,3=撤防,4=其它 運營狀態:0=空車,1=載客,2=駐車,3=停運,4=其它 GPS時間:格式yyyymmddhhnnss,北京時間 GPS經度:格式ddd.ddddddd,以度為單位。 GPS緯度:格式dd.ddddddd,以度為單位。 GPS速度:格式ddd,取值000-255內整數,以公里/小時為單位。 GPS方位:格式ddd,取值000-360內整數,以度為單位。 GPS狀態:0=無效,1=有效 結束串:回車符+換行符

資料舉例:

154747,4,2,20121130001607,116.6999512,39.9006233,0,128,1
078245,4,0,20121130001610,116.3590469,39.9909782,0,92,1
194086,4,1,20121130001610,116.5017776,40.0047951,25,220,1

那麼只需要將上述的資料欄位與資料對上就行了,一行為一條資料記錄。

首先編寫建立資料庫與表命令:

create database loaddb;
CREATE TABLE loadTable(id int primary key not null auto_increment,
carflag VARCHAR(6),touchevent CHAR(1),opstatus CHAR(1),gpstime DATETIME,
gpslongitude DECIMAL(10,7),gpslatitude DECIMAL(9,7),gpsspeed TINYINT,
gpsorientation SMALLINT,gpsstatus CHAR(
1))engine=MyISAM;

注意:上述選擇了MyISAM引擎是因為load命令使用的時候,保證資料插入的效率!

3.1 load data infile

load data infile在匯入大資料場景下非常的快!具體的說明後面會在比較的時候詳細說,這裡說一下使用語法,如下:

load data local infile "/home/light/mysql/gps1.txt" into table loadTable fields terminated by ',' lines terminated by "\n"  (carflag, touchevent, opstatus,gpstime,gpslongitude,gpslatitude,gpsspeed,gpsorientation,gpsstatus);

在使用這個命令的時候,是在MySQL的clinet端使用,登陸後敲這個命令即可!在資料欄位描述中大家會看到幾個關鍵點:以逗號為分隔符,以回車換行符,對應於上述程式碼是:

fields terminated by ',' lines terminated by "\n"

注意:更換自己的資料集路徑!

3.2 Python 批量插入

Python單條插入使用的是pymysql庫。下面是部分程式碼,完整程式碼見:

批量提交原始碼

with open('/home/light/mysql/gps1.txt', 'r') as fp:
    for line in fp:
        ...
        ...
        ...
        count += 1
        if count and count%70000==0:
            # 執行多行插入,executemany(sql語句,資料(需一個元組型別))
            self.cur.executemany(sql, data_list)
            # 提交資料,必須提交,不然資料不會儲存
            self.conn.commit()
            data_list = []
            print("提交了:" + str(count) + "條資料")
 
if data_list:
    # 執行多行插入,executemany(sql語句,資料(需一個元組型別))
    self.cur.executemany(sql, data_list)
    # 提交資料,必須提交,不然資料不會儲存
    self.conn.commit()
    print("提交了:" + str(count) + "條資料")
self.cur.close()  # 關閉遊標
self.conn.close()  # 關閉pymysql連線

上述有個關鍵點需要說明一下:

(1)使用executemany而非execute,這個提交速度要快!(2)使用批量插入,而非單條插入提交,這樣會提升效率!

3.3 Python 多執行緒插入

原始資料為一個gps1.txt檔案,這個資料太大,如果直接使用多執行緒插入,不太方便,所以先使用檔案切分方法,然後進行多執行緒的插入。

關於檔案切分,可以點選這裡:檔案切分原始碼。

Python中使用多執行緒原始碼

def multicore(self):
    file_list = [1,2324,4648,6972,9298]
    m1 = mp.Process(target=self.run, args=(file_list[0],file_list[1],'m1',))
    m2 = mp.Process(target=self.run, args=(file_list[1]+1,file_list[2],'m2',))
    m3 = mp.Process(target=self.run, args=(file_list[2]+1,file_list[3],'m3',))
    m4 = mp.Process(target=self.run, args=(file_list[3]+1,file_list[4],'m4',))
    m1.start()
    m2.start()
    m3.start()
    m4.start()
    m1.join()
    m2.join()
    m3.join()
    m4.join()

具體插入思路是使用四個執行緒分別讀取每個區間段的資料,然後再對資料進行批量插入!如果這一塊不懂的夥伴,歡迎留言哈~

3.4 MySQL資料匯入方法對比

load命令與普通的insert區別

相同點不同點
兩者都是通過讀取本地txt檔案,按照相同的分隔來讀取進行插入。 程式插入法實質為insert語句間接執行。load data設計用於在單個操作中大量載入表格資料。

效率比較

兩者耗時如下:

第一種:load data (這裡擷取的是Innodb引擎表的插入結果,當使用MyISAM時,會比現在還快!)

enter image description here

用時1h11分。

第二種:程式插入法(這裡只截取了批量插入的!)

用時:27322.45/36=7.58h

上述對比可知,load data效率非常高,原因在於使用的是load data infile方式,而第二種則為傳統的insert方式。

究其根源主要是MySQL內部對於load 和 insert的處理機制不同。

Load的處理機制是:在執行load之前,會關掉索引,當load全部執行完成後,再重新建立索引.

Insert的處理機制是:每插入一條則更新一次資料庫,更新一次索引.

另外,load與insert的不同還體現在load省去了sql語句解析,sql引擎處理,而是直接生成檔案資料塊,所以會比Insert快很多.