Sql-Server

曾經很快的慢標量函式

  • August 29, 2019

我有一個標量函式,定義如下:

CREATE FUNCTION GetUserFullname(@Id INT)
RETURNS NVARCHAR(500)
AS
BEGIN
   -- Declare the return variable here
   DECLARE @fullname NVARCHAR(500)

   -- Add the T-SQL statements to compute the return value here
   SELECT @fullname = (Firstname + ' ' + Lastname)
   FROM Account_Profiles
   WHERE UserId = @Id

   -- Return the result of the function
   RETURN @fullname
END

當我在查詢中使用此功能時,它曾經很快:

SELECT dbo.GetUserFullname(CurrentRefId) FROM OrderItems

上面的查詢有大約 50,000 行的結果。查詢曾經在 2 秒內執行,但現在突然需要 22 秒才能執行!

當我查詢時,所有不同的CurrentRefIdin值都很慢。每晚都會更新統計數據。還有一個 Total Fragmentation 75 的索引。OrderItems``SELECT dbo.GetUserFullname(CurrentRefId) FROM OrderItems

我在我的本地 SQL Server 中也有這個數據庫的副本,它在大約 1 秒內執行得非常快。

我的生產數據庫伺服器有 512 GB 記憶體和 64 個處理器。它是一個 Always On 故障轉移群集伺服器和可用性組。數據庫版本為 2012 SP2。

您正在為 OrderItems 中的每一行重新查詢 Account_Profiles 表。如果 OrderItems 有 50,000 行,那麼您將點擊 Account_Profiles 50,000 次。如果 OrderItems 變大,您將查詢更多次。如果 Account_Profiles 變得更大,那麼每個時間都將花費更長的時間。通過內聯串聯,您會看到很大的不同。(在這裡對連接列名進行假設)

Select Firstname + ' ' + Lastname FullName --other data here
FROM OrderItems oi INNER JOIN Account_Profiles ap
ON oi.userid=ap.userid

慢速伺服器上是否執行了跟踪或擴展事件?有人遇到了類似的問題,這最終成為了根本原因。

否則,您可以通過將該標量 UDF 重寫為表值函式或根本不使用該函式來永久解決該問題。

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