2016-04-02 81 views
2

我正在使用實體框架和Azure Sql db進行測試。 插入1條記錄時,動作需要400ms。加20時是2500ms。實體框架插入性能

通過EF插入1條記錄的400ms似乎很多。

EF的正常性能率是多少?

我做錯了什麼?

我知道批量插入可以改進,但我認爲一個插入可以做得更快!?

var start = DateTime.Now; 
testdbEntities testdbEntities = new testdbEntities(); 

for (int i = 0; i < 20; i++) 
    testdbEntities.Users.Add(new User{Name = "New user"}); 

testdbEntities.SaveChanges(); 

var end = DateTime.Now; 
var timeElapsed = (end - start).TotalMilliseconds; 
+0

你在桌上有索引嗎?你的互聯網連接速度如何?是在本地插入,還是在Azure服務器上生產時插入? – krillgar

+0

它是一個完整的新數據庫和表格。我有50Mbit上傳。插入與Azure上的生產幾乎相同。 – redlaz

+0

您可能有50mbit的上傳 - 但延遲是什麼?如果你距離你的天藍色數據庫100毫秒,那並不完全不相關。 – TomTom

回答

2

像所有常用的招數:

  • AutoDetectChangesEnabled =假
  • 使用過的AddRange添加
  • 等等

不行像你已經注意到了,因爲性能問題不是實體框架內,但與SQL Azure的

SQL Azure中可以看第一很酷,但它是緩慢的地獄,除非你支付了一個非常好的高級數據庫層。

由於Evk建議您應該嘗試執行一個簡單的SQL命令,如「SELECT 1」,您會注意到這可能需要超過100ms,這是非常慢的。

解決方案:

  • 移動到一個更好的SQL Azure的一級
  • 移動遠離SQL Azure的

免責聲明:我是這個項目的所有者Entity Framework Extensions

另一個解決方案是使用這個庫來批量處理多個查詢/批量操作。但是,即使這個庫很快,你也需要一個更好的SQL Azure Tier,因爲它看起來每個數據庫的往返時間都超過200毫秒。

+0

移開不是一個好的解決方案,除非問題是通用的 – TheGameiswar

+0

謝謝。這說得通。 – redlaz

+0

最近有沒有人注意到性能有所提高?我使用E.F.插入Azure SQL,並且最近發現無需更改任何內容即可顯着提高性能。 – donquijote

1

每個插入導致提交和原因日誌哈登(刷新到磁盤)。在批量寫入的情況下,這可能不會導致每次插入刷新一次(直到日誌緩衝區已滿)。因此,嘗試以某種方式對結果進行批處理,例如使用TVF

0

大多數EF應用程序使用持久性無知POCO實體和快照更改跟蹤。這意味着實體本身沒有代碼來跟蹤更改或通知更改的上下文。

當使用大多數POCO實體時,確定實體如何更改(以及因此需要將哪些更新發送到數據庫)由Detect Changes算法處理。通過檢測實體的當前屬性值與查詢或附加實體時存儲在快照中的原始屬性值之間的差異,檢測更改的工作原理。

快照更改檢測將添加到實體框架跟蹤圖中時系統中每個實體的副本。然後,隨着實體更改,每個實體都與其快照進行比較,以查看任何更改。這通過調用DetectChanges方法來實現。關於DetectChanges的重要知識是,每次被調用時它必須遍歷所有被跟蹤的實體,所以在你的上下文中越多東西越需要遍歷。

自動檢測變化所做的事情是插入發生在上下文中的事件,並在發生變化時調用檢測到的變化。

每當您添加一個新的用戶對象時,EF都會在內部跟蹤它&將新添加的對象的當前狀態保留在其快照中。 對於批量插入操作,EF首先將所有記錄插入到DB &中,然後調用DetectChanges函數。因此,批量插入所需的執行時間爲(插入所有記錄所需的時間+更新EF上下文所需的時間)。

通過禁用AutoDetectChanges,可以使數據庫插入相對更快。所以,你的代碼將是什麼樣子,

using (var context = new YourContext()) 
{ 
    try 
    { 
     context.Configuration.AutoDetectChangesEnabled = false; 

     // do your DB operations 
    } 
    finally 
    { 
     context.Configuration.AutoDetectChangesEnabled = true; 
    } 
}