欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#在MySQL大量數(shù)據(jù)下的高效讀取、寫入詳解

 更新時間:2016年11月28日 09:47:52   投稿:daisy  
最近由于工作的原因,經(jīng)常需要對海量數(shù)據(jù)進行處理,做的數(shù)據(jù)爬蟲相關,動輒千萬級別的數(shù)據(jù),單表幾十個G 都是都是家常便飯。 那么主要的開發(fā)語言是C#,數(shù)據(jù)庫使用的是MySQL。下面通過這篇文章我們來一起學習學習吧。

前言

C#操作MySQL大量數(shù)據(jù)最常見的操作便是 select 讀取數(shù)據(jù),然后在C#中對數(shù)據(jù)進行處理, 完畢后再插入數(shù)據(jù)庫中。  簡而言之就 select -> process -> insert 三個步驟。 對于數(shù)據(jù)量小的情況下(百萬級別 or 幾百兆)可能

最多1個小時就處理完了。但是對于千萬級數(shù)據(jù)可能幾天,甚至更多。 那么問題來了,如何優(yōu)化??

第一步 解決讀取的問題

跟數(shù)據(jù)庫打交道的方式有很多,我來列舉下吧:

1. 【重武器-坦克大炮】使用重型ORM框架,比如 EF,NHibernat 這樣的框架。

2. 【輕武器-AK47】 使用 Dapper,PetaPoco 之類,單cs文件。靈活高效,使用簡單。居家越貨必備(我更喜歡PetaPoco :))

3. 【冷兵器?匕首?】使用原生的Connection、Command。 然后寫原生的SQL語句。。

分析:

【重武器】在我們這里肯定直接被PASS, 他們應該被用在大型項目中。

【輕武器】 Dapper,PetaPoco 看過源碼你會發(fā)現(xiàn)用到了反射,雖然使用 IL和緩存技術 ,但是還是會影響讀取效率,PASS

好吧那就只有使用匕首, 原生SQL 走起, 利用 DataReader 進行高效讀取,并且使用 索引 取數(shù)據(jù)(更快),而不是列名。

大概的代碼如下:

using (var conn = new MySqlConnection("Connection String..."))
{
 conn.Open();
 //此處設置讀取的超時,不然在海量數(shù)據(jù)時很容易超時
 var c = new MySqlCommand("set net_write_timeout=9999999; set net_read_timeout=9999999", conn);
 c.ExecuteNonQuery();

 MySqlCommand rcmd = new MySqlCommand();
 rcmd.Connection = conn;
 rcmd.CommandText = @"SELECT `f1`,`f2` FROM `table1`";
 //設置命令的執(zhí)行超時
 rcmd.CommandTimeout = 99999999;
 var myData = rcmd.ExecuteReader();

 while (myData.Read())
 {
  var f1= myData.GetInt32(0);
  var f2= myData.GetString(1);
  //這里做數(shù)據(jù)處理....
 }
}

哈哈,怎么樣,代碼非常原始,還是使用索引來取數(shù)據(jù),很容易出錯。  當然一切為了性能咱都忍了

第二步 數(shù)據(jù)處理

其實這一步,根據(jù)你的業(yè)務需要,代碼肯定不一, 不過無非是一些 字符串處理 , 類型轉換 的操作,這時候就是考驗你的C#基礎功底的時候了。 以及如何高效編寫正則表達式。。。

具體代碼也沒法寫啊 ,先看完 CLR via C# 在來跟我討論吧 ,O(∩_∩)O哈哈哈~ 跳過。。。。

第三部 數(shù)據(jù)插入

如何批量插入才最高效呢?  有同學會說, 使用 事務 啊,BeginTransaction, 然后EndTransaction。 恩,這個的確可以提高插入效率。 但是還有更加高效的方法,那就是合并insert語句。

那么怎么合并呢?

insert into table (f1,f2) values(1,'sss'),values(2,'bbbb'),values(3,'cccc');

就是把values后面的全部用逗號,鏈接起來,然后一次性執(zhí)行 。

當然不能一次性提交個100MB的SQL執(zhí)行,MySQL服務器對每次執(zhí)行命令的長度是有限制的。 通過 MySQL服務器端的 max_allowed_packet   屬性可以查看, 默認是 1MB

咱們來看看偽代碼吧

 //使用StringBuilder高效拼接字符串
 var sqlBuilder = new StringBuilder();
 //添加insert 語句的頭
 string sqlHeader = "insert into table1 (`f1`,`f2`) values";
 sqlBuilder.Append(sqlHeader);
 using (var conn = new MySqlConnection("Connection String..."))
 {
  conn.Open();
  //此處設置讀取的超時,不然在海量數(shù)據(jù)時很容易超時
  var c = new MySqlCommand("set net_write_timeout=9999999; set net_read_timeout=9999999", conn);
  c.ExecuteNonQuery();

  MySqlCommand rcmd = new MySqlCommand();
  rcmd.Connection = conn;
  rcmd.CommandText = @"SELECT `f1`,`f2` FROM `table1`";
  //設置命令的執(zhí)行超時
  rcmd.CommandTimeout = 99999999;
  var myData = rcmd.ExecuteReader();
  while (myData.Read())
  {
   var f1 = myData.GetInt32(0);
   var f2 = myData.GetString(1);
   //這里做數(shù)據(jù)處理....
   sqlBuilder.AppendFormat("({0},'{1}'),", f1,AddSlash(f2));
   if (sqlBuilder.Length >= 1024 * 1024 * 1024)//當然這里的1MB length的字符串并不等于 1MB的Packet。。。我知道:)
   {
    insertCmd.Execute(sqlBuilder.Remove(sqlBuilder.Length-1,1).ToString())//移除逗號,然后執(zhí)行
    sqlBuilder.Clear();//清空
    sqlBuilder.Append(sqlHeader);//在加上insert 頭
   }
  }
}

好了,到這里 大概的優(yōu)化后的高效查詢、插入就完成了。

總結

總結下來,無非2個關鍵技術點, DataReader、SQL合并, 都是一些老的技術啦。其實,上面的代碼只能稱得上高效, 但是, 卻非常的不優(yōu)雅。以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家能有所幫助,如果有疑問大家可以留言交流。

相關文章

  • c# 通過代碼開啟或關閉防火墻

    c# 通過代碼開啟或關閉防火墻

    這篇文章主要介紹了c# 通過代碼開啟或關閉防火墻的示例,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下
    2020-10-10
  • C#從命令行讀取參數(shù)的方法

    C#從命令行讀取參數(shù)的方法

    這篇文章主要介紹了C#從命令行讀取參數(shù)的方法,實例分析了C#命令行讀取參數(shù)的實現(xiàn)技巧與操作流程,需要的朋友可以參考下
    2015-04-04
  • C#修改及重置電腦密碼DirectoryEntry實現(xiàn)方法

    C#修改及重置電腦密碼DirectoryEntry實現(xiàn)方法

    這篇文章主要介紹了C#修改及重置電腦密碼DirectoryEntry實現(xiàn)方法,實例分析了C#修改及重置電腦密碼的相關技巧,需要的朋友可以參考下
    2015-05-05
  • C#隱式/顯示實現(xiàn)接口方法詳解

    C#隱式/顯示實現(xiàn)接口方法詳解

    這篇文章主要為大家詳細介紹了C#隱式/顯示實現(xiàn)接口方法,接口的使用場景介紹,感興趣的小伙伴們可以參考一下
    2016-03-03
  • winform實現(xiàn)限制及解除鼠標移動范圍的方法

    winform實現(xiàn)限制及解除鼠標移動范圍的方法

    這篇文章主要介紹了winform實現(xiàn)限制及解除鼠標移動范圍的方法,涉及C#控制WinForm鼠標事件屬性的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-09-09
  • C# WinForm編程獲取文件物理路徑的方法

    C# WinForm編程獲取文件物理路徑的方法

    這篇文章主要介紹了C# inForm編程獲取文件物理路徑的方法,獲取的物理路徑是軟件即軟件安裝所在目錄,需要的朋友可以參考下
    2014-08-08
  • C#連接Oracle的方法實例總結

    C#連接Oracle的方法實例總結

    這篇文章主要介紹了C#連接Oracle的方法,結合實例形式總結分析了幾種常見的C#連接Oracle數(shù)據(jù)庫的操作技巧與相關注意事項,需要的朋友可以參考下
    2017-06-06
  • 淺談C#在網(wǎng)絡波動時防重復提交的方法

    淺談C#在網(wǎng)絡波動時防重復提交的方法

    這篇文章主要介紹了淺談C#在網(wǎng)絡波動時防重復提交的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04
  • 基于C#編寫一個遠程桌面應用

    基于C#編寫一個遠程桌面應用

    封閉環(huán)境無法拷貝外來的遠程桌面軟件,所以這篇文章小編就來帶大家用C#編寫一個簡單的遠程桌面應用,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-10-10
  • 枚舉的用法詳細總結

    枚舉的用法詳細總結

    本篇文章主要是對枚舉的用法進行了詳細的總結介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2014-01-01

最新評論