SQL Server 會緩存查詢計劃以避免重複編譯。使用參數化查詢原可重用計劃,但 LINQ to SQL 產生的參數若未指定固定長度(特別是 nvarchar),會導致相同 SQL 文字因參數長度不同而產生多份計劃,嚴重消耗 CPU。
var video1 = ctx.Videos.SingleOrDefault(v => v.Introduction == "Hello");
var video2 = ctx.Videos.SingleOrDefault(v => v.Introduction == "Hello World");
產生的 SQL 完全相同,但 sys.syscacheobjects 顯示兩筆快取記錄,差異在於 @p0 的 Size 分別為 5 與 11。
ADO.NET 中 SqlParameter 若為 nvarchar 且未設定 Size,實際長度會隨傳入值動態決定,導致 SQL Server 視為不同參數而無法重用計劃。
param.Size = 固定值 即可解決。@p0, @p1...),無直接介入點。雖可嘗試覆寫 SubmitChanges 修改 SqlCommand 參數,但:
SubmitChanges 僅影響更新操作,查詢操作(佔比 90%+)無法受益。此問題在 LINQ to SQL 目前無完美解法。所幸實務上「查詢條件使用長度不一的字串參數」情境較少,影響相對有限。若極度在意計劃重用,可考慮改用預存程序或手寫參數化 SQL。