2014-07-22 35 views
1

我有一個應用程序從多個套接字接收數據,然後將數據寫入數據庫。如何提高實體框架批量插入

我目前使用EF來做到這一點。我想知道如何讓它更有效率。

我已閱讀,做批量插入是每500個insters快,所以我只能將更改保存到DB:

db.Logs_In.Add(tableItem); 
      if (logBufferCounter++ > 500) 
      { 
       db.SaveChanges(); 
       logBufferCounter = 0; 
      } 

現在我已經成型的應用和工作的74%是由做功能:System.Data.Enitity.DbSet'1[System._Canon].Add

有沒有更好的方法來做插入?也許可以將tableItems排隊到List中,然後將整個列表添加到DB Context中。

或者也許我看着這一切都錯了,我應該完全避免使用EntityFramework這個更高的性能插入?目前,它是我應用程序中的瓶頸,如果我查看系統資源,SQL甚至不會像眼瞼一樣。

所以我的問題:

1:以什麼方式,我將實現對多個插入

2最有效的/最快插入:如果EF是可以接受的,我怎麼能提高我的解決方案?

我正在使用SQL Server 2012企業版, 傳入數據是一個常量流,但我可以承受緩衝它,然後做一個批量插入,如果這是一個更好的解決方案。

[編輯]

爲了進一步解釋情況。我有一個線程正在一個concurrentQueue上循環,該隊列從隊列中取出隊列。但由於db插入是瓶頸的事實。隊列中通常會有數千個條目,所以如果還有一種異步或並行方式,我可以使用多個線程來執行插入操作。

+1

很好的討論在這裏http://stackoverflow.com/a/5942176/1663001高頻插入。 – DavidG

+1

@DavidG,謝謝,如果我去EF路線,這真的有幫助,我提出了建議更改,我已經有100倍的性能提高。 – Zapnologica

+0

太棒了,我希望這對你來說已經足夠了。如果沒有,那麼馬克的答案就是要走的路。 – DavidG

回答

4

對於涉及大量插入的場景,我傾向於單獨使用「緩衝區」(內存中,或重做列表或其他),然後作爲批處理作業(可能是每分鐘或每隔幾分鐘)閱讀列表並使用SqlBulkCopy儘可能高效地將數據扔入數據庫。爲此,我使用方法fastmember,該方法將List<T>(或任何IEnumerable<T>)作爲IDataReader公開,可將其送入SqlBulkCopy,將T的屬性暴露爲數據讀取器中的邏輯列。所有你需要做的就是從緩衝區填入List<T>

但是,請注意,您需要考慮「出現問題」的情況;即如果插入失敗一半,你如何處理緩衝區中的數據?這裏的一個選擇是將SqlBulkCopy轉換爲轉換成轉換表(相同的模式,但不是「實時」轉換表),然後使用常規的INSERT在知道數據在數據庫時以一步完成數據複製 - 這使得恢復更簡單。

+0

+1對錯誤問題,是否有一些如何插入所有的工作,然後可能把失敗的插入到一個失敗的表? – Zapnologica

+1

@Zapnologica,這取決於錯誤的性質。如果錯誤是你的sql服務器連接中斷了,那麼......你打算怎麼做?事實上,因爲'SqlBulkCopy'沒有告訴你它有多遠(更不用說告訴你日誌文件的前滾部分是什麼,如果數據庫服務器完全崩潰),你的選擇是有限的。如果您可以在以後的重試中補償重複項,則「重新啓動」策略是合理的。 「數據不重要**;我不關心我們是否從一批中丟失了幾行」策略有時也可能是有效的。 –