国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

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

2019-10-29 21:18:55
字體:
供稿:網(wǎng)友

前言

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, 他們應(yīng)該被用在大型項目中。

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

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

大概的代碼如下:

using (var conn = new MySqlConnection("Connection String...")){ conn.Open(); //此處設(shè)置讀取的超時,不然在海量數(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`"; //設(shè)置命令的執(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ù),很容易出錯。  當(dāng)然一切為了性能咱都忍了

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

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

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

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

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

那么怎么合并呢?

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

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

當(dāng)然不能一次性提交個100MB的SQL執(zhí)行,MySQL服務(wù)器對每次執(zhí)行命令的長度是有限制的。 通過 MySQL服務(wù)器端的 max_allowed_packet   屬性可以查看, 默認(rèn)是 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è)置讀取的超時,不然在海量數(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`";  //設(shè)置命令的執(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)//當(dāng)然這里的1MB length的字符串并不等于 1MB的Packet。。。我知道:)   {    insertCmd.Execute(sqlBuilder.Remove(sqlBuilder.Length-1,1).ToString())//移除逗號,然后執(zhí)行    sqlBuilder.Clear();//清空    sqlBuilder.Append(sqlHeader);//在加上insert 頭   }  }}

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

總結(jié)

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


注:相關(guān)教程知識閱讀請移步到c#教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 浦北县| 屏东市| 安平县| 平果县| 六枝特区| 吐鲁番市| 永丰县| 邯郸县| 济阳县| 丰顺县| 武定县| 林芝县| 南充市| 正镶白旗| 涟水县| 阿克| 张北县| 泽库县| 电白县| 商水县| 永丰县| 濮阳市| 海淀区| 栾川县| 灵山县| 麻阳| 白城市| 绥化市| 庆城县| 高雄县| 会泽县| 开化县| 云霄县| 自治县| 登封市| 孙吴县| 大足县| 梁河县| 板桥市| 盐山县| 浑源县|