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

首頁 > 學院 > 開發(fā)設計 > 正文

一次EF批量插入多表數(shù)據(jù)的性能優(yōu)化經歷

2019-11-17 02:17:49
字體:
來源:轉載
供稿:網友

一次EF批量插入多表數(shù)據(jù)的性能優(yōu)化經歷

距離上次的博客已經有15個多月了,感慨有些事情還是需要堅持,一旦停下來很有可能就會停很久或者從此再也不會堅持。但我個人一直還堅持認為屬于技術狂熱份子,且喜歡精益求精的那種。最近遇到兩個和數(shù)據(jù)遷移相關的項目,均遇到需要性能優(yōu)化的問題,這里拿第二個項目的一個小優(yōu)化過程與大家分享,技術并不高深,我注重的是解決問題的過程。我的方案是有業(yè)務背景以及技術背景限制的,不一定適合其它項目,優(yōu)化是相對的。

業(yè)務場景:我們需要遷移一批老的合同訂單數(shù)據(jù),其有一個合同的訂單數(shù)為519條,遷移到新表中會涉及到主要的4個表,就是說519條老數(shù)據(jù),會變成519*4。 技術背景:數(shù)據(jù)庫MySQL,后臺采用的是微軟的EF

問題:遷移這批訂單當時最好的性能方案是14秒(未優(yōu)化前是分鐘級別),我們總共有400000訂單,算下最理想狀態(tài)下的總時間:=(14/519)*400000/3600=3小時,再算下取數(shù)據(jù),轉換數(shù)據(jù)的時間,基本要4小時。如果中途有異常,這個時間可能需要一夜甚至更長的時間才能遷移完,這真正惡夢。 先來看看優(yōu)化前:優(yōu)化前導519個合同是分鐘級別的,看下代碼后我的方案是分三步:

1:按批次,比如10個合同一批來操作,將后續(xù)需要的數(shù)據(jù)全部取出來。原方案是用到哪查到哪,試想400000的訂單還不查個一天兩天的。 2:轉換數(shù)據(jù),將源數(shù)據(jù)轉換成新的對象集合,此處不操作數(shù)據(jù)庫。 3:批量插入數(shù)據(jù),將轉換后校驗無誤的數(shù)據(jù)導入數(shù)據(jù)庫,原方案是邏輯到哪,哪就插入數(shù)據(jù)庫。不便于定位性能瓶頸也不方便進行有針對性的優(yōu)化。 根據(jù)以上三個步驟,我們就很容易精確定位是哪方面慢了,是查詢數(shù)據(jù)庫慢,轉換數(shù)據(jù)慢,還是插入數(shù)據(jù)庫慢。 經過此方面調整后的結果: 1:一次性讀取數(shù)據(jù)后,性能明顯提升,降低了數(shù)據(jù)庫讀取次數(shù),享受到了批量取數(shù)據(jù)的好處; 2:定位到性能瓶頸在于數(shù)據(jù)庫插入,總時間15秒,保存數(shù)據(jù)花了14秒

疑惑:我對保存519*4條數(shù)據(jù)需要14秒的結果不滿意,我堅定認為數(shù)據(jù)庫插入如此小數(shù)量級的數(shù)量不需要這么長的時間。再次分析,發(fā)現(xiàn)我們需要保存多張表的數(shù)據(jù),且相互之間存在依賴關系,即第二張表的數(shù)據(jù)需要第一張表插入后的主鍵,這樣我們在寫EF時,會出現(xiàn)多條SaveChange的方法。519個訂單做循環(huán),SaveChange的總次數(shù):519*3。 改造:分三次數(shù)據(jù)庫操作 1:先全量保存第一個被依賴的表,此時由于EF的數(shù)據(jù)追蹤功能,插入數(shù)據(jù)庫后,對象上會自動賦值主鍵信息; 2:再全量保存第二個被依賴的表,由于被依賴的表在第一步已經更新成功,此處能夠成功獲取到外鍵; 3:最后全量保存第三被依賴的表。

此方案的SaveChange次數(shù)降低到3次,執(zhí)行時間變更5.5秒,性能提高接近200%。 數(shù)據(jù)庫事務,如果我們的操作加上事務會怎樣?我們從優(yōu)化前的版本開始看(不是上面提到的分打開三次數(shù)據(jù)庫批量操作):主要利用TransactionScope來完成

using (var trans = new TransactionScope(TransactionScopeOption.Required,                   new TransactionOptions()                   {                       Timeout = new TimeSpan(0, 0, 240),                       IsolationLevel =                           System.Transactions.IsolationLevel.RepeatableRead                   }))

1:519*3次SaveChange,最外層嵌套一個大事務,不嵌套是58秒,嵌套了50秒,兩者相關不大,如果是一個DbContext出現(xiàn)大量的SaveChange,有事務從結果來看性能更優(yōu)化,具體原因不明,待調查。 2:519*3次SaveChange,縮小事務范圍,將事務放在循環(huán)體內部,結果變成14秒,看來小事務還是值得推薦的。 再看改造后的分三次數(shù)據(jù)庫操作每次一次SaveChange的場景:外面嵌套一個大事務,嵌套是5.5秒,不嵌套是5.8,相差不大。

單一職責,上面的批量插入數(shù)據(jù)庫使用了三次打開數(shù)據(jù)庫,每次只有一個SaveChange,那么在一個DbContext中操作調用三次SaveChange呢? 在一個DbContext中做三次SaveChange是32秒,采用三個DbContext分開操作是5.5秒,結論是大批量數(shù)據(jù)插入,避免在同一DbContext中做多次SaveChange。

結論:

1:避免使用大的數(shù)據(jù)庫事務,盡量控制在有需求時打開,不需要時及時關閉,它會鎖定資源的;

2:批量插入表數(shù)據(jù),盡量避免在同一DbContext下做多次SaveChange操作;

3:如果有大批數(shù)據(jù)需要插入表,盡量采用單表集中插入后再操作后續(xù)表,避免插入一條數(shù)據(jù)SaveChange一次;

4:讀取數(shù)據(jù)盡量按批量讀取,避免取一條數(shù)據(jù)讀取一次:查詢100次單條記錄與一次性查詢100條記錄是有很大差距的。


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 江达县| 县级市| 深泽县| 乌苏市| 平舆县| 泗洪县| 汉阴县| 砀山县| 新化县| 蓝山县| 锡林郭勒盟| 云南省| 宿州市| 黄石市| 仁怀市| 千阳县| 磴口县| 商南县| 应城市| 壶关县| 吴川市| 乡宁县| 双牌县| 历史| 海丰县| 宣化县| 洛扎县| 康平县| 陵水| 化德县| 南投市| 渭源县| 军事| 麻城市| 新化县| 葵青区| 蓬安县| 衡南县| 桂阳县| 信宜市| 光山县|