簡體   English   中英

為什么相同的Linq-to-SQL查詢在數據庫服務器上為不同的項目消耗了更多的CPU時間?

[英]Why does the same Linq-to-SQL query consume much more CPU time on the database server for a different project?

我有一個遺留的.Net 4項目(名稱為“A”) ,它使用Linq-to-SQL查詢數據庫,我有另一個.Net 4項目(命名為“B”),其中包含類似但不同的查詢代碼與“A”相同的數據庫。

兩個項目:

  • 是C#項目{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
  • 使用相同的程序集(版本v4.0.30319,相同的文件夾)
    • System.dll中
    • System.Data.dll中
    • System.Data.Linq.dll

自動生成的DataContext特定於每個項目,但實例化方式相同:

  • 使用SQL身份驗證的相同連接字符
  • 兩個DataContext都將其CommandTimeout從默認值設置為60秒
  • DataContext的所有其他配置選項都是默認值

構造Linq查詢的方式對於項目來說並不完全相同,但生成的Linq查詢是相同的。 生成的(T-)SQL select語句也是一樣的! (監視並驗證數據庫服務器上的SQL句柄)

數據庫服務器是:

  • Microsoft SQL Server Enterprise 2005 x64(9.00.4035.00)
  • 操作系統:Microsoft Server 2003 R2 SP2 x64

如果運行,則監視的CPU時間(在數據庫服務器上)對於項目“A”的查詢急劇增加,並且拋出了命令超時異常。 (System.Data.SqlClient.SqlException:超時已過期)

另一方面,“B”的查詢在幾秒鍾內(大約3)執行 我能夠通過再次調用具有相同參數的“A”代碼來重現行為(不對代碼或數據庫進行更改) “B”甚至在幾秒鍾內執行,同時“A”增加了CPU時間。

令人遺憾的是,在一位同事重新創建指數之后,我再也無法重新表達這種行為。 同一位同事提到該查詢“上個月”運行得很快(盡管沒有代碼從“上個月”改變了......)。

我調試了兩個項目的代碼 - 兩個DataContext實例看起來都很相似。 db服務器進程的sql句柄包含相同的SQL語句。 但是“A”拋出超時異常並且“B”在幾秒鍾內執行 - 重復!

為什么相同的Linq-to-SQL查詢在項目“A”和“B”的數據庫服務器上消耗的CPU時間要多得多?

確切地說:如果查詢由於原因而運行“慢” - 重復 - 同一個查詢如何運行得更快只是因為它被另一個Linq-to-SQL代碼調用?

(還有)我不知道的副作用嗎? 是否有一些DataContext的實例值我必須特別關注運行時?

順便說一句:SQL語句 - 通過SSMS - 在每次運行時都使用相同的查詢計划。

為了完整起見,我將以下樣本鏈接起來:

  • 項目“B”的C#代碼片段(兩個項目的SqlRequest.GetQuery部分看起來相似)
  • SQL文件包含適當的數據庫架構
  • 數據庫執行計划

請記住,我不能透露完整的數據庫模式,也不能透露我要查詢的代碼和實際數據。 (SQL表在命名的列旁邊有其他列,而C#代碼有點復雜,因為Linq查詢是有條件構造的。)

更新 - 在運行時更深入了解

兩個DataContext實例的一些屬性:

Log = null;
Transaction = null;
CommandTimeout = 60;
Connection: System.Data.SqlClient.SqlConnection;

SqlConnection是從類似的連接字符串創建的(兩種情況):

"Data Source=server;Initial Catalog=sourceDb;Persist Security Info=True;User ID=user;Password=password"

沒有運行顯式SqlCommands來將SET選項傳遞給數據庫會話。 兩者都不包含內聯TVF SET選項。

您需要在SQL Server上運行跟蹤 ,而不是從C#端調試它。 這將顯示AB在服務器上執行的所有操作。 執行計划對你沒有好處,因為正是這個 - 只是一個計划。 您希望查看確切的語句及其實際性能指標。

在極少數情況下,您要告訴我兩個SELECT語句完全相同但性能差異很大,我幾乎可以肯定它們在不同的事務隔離級別下運行。 即使您沒有明確創建任何SQL命令,單個SQL命令也是隱式事務。

如果由於某種原因跟蹤不清楚,您應該發布正在運行的命令及其指標。

注意:運行跟蹤會產生一些性能開銷,因此如果可能的話,我會盡量保持時間范圍較小或在非高峰期運行。

我想你會在你的“A”項目edmx文件中檢查LazyLoadingEnabled =“true”。

如果LazyLoadingEnabled =“true”:在延遲加載的情況下,相關對象(子對象)在被請求之前不會自動加載其父對象。 默認LINQ支持延遲加載。

如果LazyLoadingEnabled =“false”:在急切加載的情況下,相關對象(子對象)將自動加載其父對象。 要使用Eager加載,您需要使用Include()方法。

暫無
暫無

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

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