Sql-Server-2016

AddWithValue 性能和計劃記憶體影響

  • January 23, 2018

最近我注意到我公司的應用程序使用AddWithValue將參數值傳遞給動態的參數化查詢。例子:

cmd.Parameters.AddWithValue("@VehicleId", Vehicles.VehicleId);

在數據庫中,數據類型VehicleIDINT.

據我了解,由於 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()(即使在您“知道”問題不存在的情況下):

引用自:https://dba.stackexchange.com/questions/195937