簡體   English   中英

實體框架4:SQL Server 2008的性能不佳

[英]Entity Framework 4 : Bad performance with SQL Server 2008

我正在開發一個基於Entity Framework的軟件來處理MS SQL Server 2008數據庫中的數據。

[麻煩1]

我剛嘗試從我的程序中將一些小數據( 大約2 Mb )插入到數據庫中:性能非常糟糕! 插入這些數據需要1分鍾以上

我試着生成預編譯的視圖,我得到了相同的結果:-(

我的所有代碼都使用業務層(使用帶有T4模板的.edmx文件自動生成)來管理服務層中的數據。 在對象關系中導航是非常實際的。

如何使用Entity Framework提高這些插入的性能?

[麻煩2]

此外,在使用SaveChanges()方法在數據庫中插入數據之前,我使用AddObject()方法填充對象上下文。 我使用AddObject()向我的對象上下文添加大約10萬個小對象(大約2 Mb):它需要很長時間(超過10分鍾)!

我怎樣才能減少這個時間?

UPDATE

我的程序必須在不到2-3分鍾的時間內在數據庫中保存超過50 Mb的數據? 您認為EF可以實現嗎?

您可以使用Entity Framework Profiler來檢查正在生成的SQL。 此工具有30天的免費試用期。 它還聲稱它可以做“分析和檢測使用實體框架時常見的陷阱”。

還有關於EF調整的這篇文章

編輯

根據您的編輯,EF不是要走的路。 您需要進行批量插入才能快速獲取數據。 看看這個鏈接,我幫助有人將負載時間從10小時減少到6分鍾。

EF(和LINQ2SQL就此而言)每條記錄只進行一次更新/插入。 這通常導致批量插入/更新的性能低於可接受的性能。 解決方法是創建存儲過程,為您執行這些任務。 在大多數情況下,當您對少量對象類型執行這些操作時,這是可接受的解決方案,在這種情況下,使用EF仍然可行,並手動編寫這些SP,然后將它們添加到EDMX。 您可以谷歌在EF中使用存儲過程。

這里有幾種可能性。

  1. 數據庫硬件可能無法完成處理100,000個插入的任務。 涉及多少個表? 是否存在諸如觸發器等輔助因素? 數據庫內存是否受限?

  2. Web服務器硬件可能無法承擔處理這么多負載的任務。 數據源自何處? 轉移到Web服務器需要多長時間? Web服務器實際發送到數據庫服務器的插入數/秒是多少?

總而言之,您必須進行分析以確定瓶頸的確切位置。 根據您迄今為止提供的信息,它可能在任何地方。

您需要在Web服務器上運行探查器,並且需要在數據庫服務器上使用SQL事件探查器。 此外,您應該在加載數據時監視計算機的CPU,內存和網絡使用情況圖。

獲得所有這些數據后,您應該能夠確定問題所在。

UPDATE
作為旁注,EF必須創建至少100,000個對象來保存要上載的數據(每個記錄一個)。 這有它自己的開銷,這就是為什么ORM通常不適合大規模插入/更新數據。

更新2
如果您在完全相同的台式機上運行客戶端和數據庫服務器,那么您可能會遇到硬件問題。 希望您擁有一個至少4 GB內存的多核系統。 您系統上的所有內容都將爭奪資源:visual studio,SQL Server,應用程序本身,以及您正在運行的任何其他內容。 Studio和SQL Server是內存和CPU占用的。 (僅供參考 - SQL Server不向任務管理器報告所有內容)

重點是,除非您使用嵌入式SQL服務器部署應用程序,否則這不會接近真實世界的測試,您所看到或缺乏的性能與現實世界的情況無關。

正如其他人已經或多或少地指出的那樣,實體框架的工作原理是為每個對象發送一個語句,然后再一個語句來獲取數據庫分配的ID值。

在許多對象上運行時,這非常慢,特別是如果數據庫服務器的往返時間超過1毫秒。

為了在將許多對象存儲到數據庫時提高性能,請使用SqlBulkCopy類而不是Entity Framework。

您可以在本文中找到Entity Framework和SqlBulkCopy之間的完整比較: 如何將復雜對象批量插入SQL Server數據庫

您可以使用SQL Server Profiler對查詢進行概要分析,然后使用數據庫引擎優化顧問來確定要添加的更好的統計信息和索引。

有可能它不是實體框架,而是您的數據庫架構是罪魁禍首,例如壞的聚簇索引或太多的索引。

您可以使用ObjectQuery.ToTraceString屬性查看Entity Framework生成的SQL。

如果實體框架生成的SQL不能滿足您的需求,您可以使用自己的存儲過程進行創建,更新和刪除操作。

在最初的問題中,我得到的印象是,一次創建了100,000個左右的對象,並且只進行了一次SaveChanges調用。 這種對SaveChanges進行單次調用的大型工作單元對於實體框架來說幾乎總是一個非常糟糕的性能想法。 我會嘗試將一些批次分成大約100個對象,並在每個批次之間調用SaveChanges。 事實上,我甚至會處理上下文並在批處理之間創建一個新的上下文,因為否則你會立即在狀態管理器中結束所有這些對象,這會產生開銷。 您可能需要嘗試不同的批量大小才能找到最佳數量。

此外,您可能想要考慮使用的實體類型。 如果使用poco實體,則會有一些開銷檢測更改,當您使用實現IEntityWithChangeTracking的類(或從實現該接口的EntityObject繼承)時,這些更改不存在。

  • 丹尼

我正在遇到與我當前項目類似的問題。 我附加到SQL事件探查器並啟動了我的進程。 每次保存更改時,實體框架似乎都會為每個INSERT或UPDATE啟動一個SQL事務。

我不確定這是否與此問題有關,但我會運行SQL事件探查器並檢查結果。 我還會監視SQL框上的磁盤使用情況(讀取和寫入)(如果可能),看看是否有任何紅色標記。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM