AddWithValue 性能和計劃記憶體影響
最近我注意到我公司的應用程序使用
AddWithValue
將參數值傳遞給動態的參數化查詢。例子:cmd.Parameters.AddWithValue("@VehicleId", Vehicles.VehicleId);
在數據庫中,數據類型
VehicleID
為INT
.據我了解,由於 AddWithValue(已棄用)未指定數據類型/長度,因此此“@VehicleID”已轉換並且可能轉換不正確。在“INT”的情況下,這種轉換會影響 SQL Server 的性能嗎?
這會導致超出計劃記憶體污染的問題嗎?轉換是否會導致性能下降?
我強烈建議始終使用允許您顯式設置數據類型和精度的方法。是的,這需要更多的工作,無論是前期還是如果數據庫中的數據類型發生變化(例如,當
IDENTITY
列超出範圍int
並將其升遷為時,這很常見bigint
)。cmd.parameters.Add("@VehicleId", SqlDbType.Int).Value = Vehicles.VehicleId;
這只是更好的做法,因為其他形式的
AddWithValue()
可能會導致問題。例如,這裡會推斷出錯誤的類型:cmd.parameters.AddWithValue("@intParam", 5); -- tinyint cmd.parameters.AddWithValue("@intParam", 257); -- smallint cmd.parameters.AddWithValue("@varchar20", "bob"); -- nvarchar(3) cmd.parameters.AddWithValue("@varchar20", "frank"); -- nvarchar(5)
在該
int
範圍內,您不太可能遇到很多問題,但是如果您將其擴展到其他類型,並且使用臨時查詢而不是具有強類型參數的儲存過程呼叫,那麼事情很快就會變得非常糟糕. 正如 David 指出的那樣,您可能會遇到糟糕的計劃,例如可以使搜尋切換到掃描的隱式轉換。允許將預設值nvarchar
傳遞給varchar
列可能會導致嚴重的性能問題,正如Jonathan Kehayias 在此處展示的那樣. 並且允許 .NET 根據字元串的長度來確定參數的長度 - 根據 SQL Server 的版本和參數化設置 - 會為傳入的每個唯一長度的字元串制定不同的計劃。這不會使那些特定查詢速度較慢,但它們會浪費大量記憶體,因為每個長度都會儲存和使用一個冗餘計劃。這個問題在其他地方也有人問過:
Joel Coehoorn也寫過關於類型轉換問題的部落格,建議您遠離
AddWithValue()
(即使在您“知道”問題不存在的情況下):