使用 SQL 标量函数的查询如何在 5 分钟内从 运行 变为 5 小时
How can a query with a SQL scalar function go from running in 5 minutes to 5 hours
我一直在使用这个功能,它很常用来删除非字母数字字符。
ALTER Function [dbo].[RemoveNonAlphaCharacters](@Temp VarChar(1000))
Returns VarChar(1000)
AS
Begin
Declare @KeepValues as varchar(50)
Set @KeepValues = '%[^a-z0-9]%'
While PatIndex(@KeepValues, @Temp) > 0
Set @Temp = Stuff(@Temp, PatIndex(@KeepValues, @Temp), 1, '')
Return @Temp
End
这从 运行宁用了 5 分钟变成了 5 小时。是什么原因造成的?当我从查询中删除函数时,它会在 5 分钟内返回完成。此查询已 运行 数百次。
数据还是一样,索引还是一样,没有碎片化。磁盘space 180GB左右也足够了,内存也很充足,基本上,两个运行之间没有任何变化。我还检查了 SQL 探查器是否有任何痕迹,但我只能找到 运行 的内部痕迹,主要是 Microsoft Telemetry 服务(2016 开发人员版)
我真的很困惑,我知道标量函数不是最有效的,但是 运行ning 时间的急剧增加让我感到困惑。
正如我在评论中提到的,您的问题在这里有 2 倍:
- 您有一个 Multi-line 标量函数,众所周知,它通常性能不佳。 (即使您使用 SQL Server 2019,该函数也不会内联。)
- 你的函数中有一个
WHILE
,do 表现不佳,因为 SQL 是一种 set-based 语言,因此不是为了很好地执行迭代过程。
我假设该函数的意图是它执行它调用的操作,并且只保留字符串中的数字和字母。由于您没有注意到版本,因此我建议使用内联 table-value 函数。我将 假设 ,但是,您可以访问足够新的版本来使用 STRING_AGG
不过:
CREATE FUNCTION dbo.RemoveNonAlphaCharacters (@InputString varchar(1000))
RETURNS table
AS RETURN
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT TOP (LEN(@InputString))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3),
Chars AS(
SELECT I,
SUBSTRING(@InputString,I,1) AS C
FROM Tally)
SELECT STRING_AGG(C,'') WITHIN GROUP (ORDER BY I) AS OutputString
FROM Chars
WHERE C LIKE '[A-z]'
OR C LIKE '[0-9]';
然后你可以在 FROM
:
中使用 CROSS APPLY
调用所述函数
SELECT V.YourString,
RNAC.OutputString
FROM (VALUES('abc 123-789'),('Apples & Pears'),('Mr O''Mally'))V(YourString)
CROSS APPLY dbo.RemoveNonAlphaCharacters(V.YourString) RNAC;
如果您使用的不是最新版本的 SQL 服务器,则需要将 STRING_AGG
调用替换为“旧”FOR XML PATH
(以及 STUFF
) 方法。
我一直在使用这个功能,它很常用来删除非字母数字字符。
ALTER Function [dbo].[RemoveNonAlphaCharacters](@Temp VarChar(1000))
Returns VarChar(1000)
AS
Begin
Declare @KeepValues as varchar(50)
Set @KeepValues = '%[^a-z0-9]%'
While PatIndex(@KeepValues, @Temp) > 0
Set @Temp = Stuff(@Temp, PatIndex(@KeepValues, @Temp), 1, '')
Return @Temp
End
这从 运行宁用了 5 分钟变成了 5 小时。是什么原因造成的?当我从查询中删除函数时,它会在 5 分钟内返回完成。此查询已 运行 数百次。
数据还是一样,索引还是一样,没有碎片化。磁盘space 180GB左右也足够了,内存也很充足,基本上,两个运行之间没有任何变化。我还检查了 SQL 探查器是否有任何痕迹,但我只能找到 运行 的内部痕迹,主要是 Microsoft Telemetry 服务(2016 开发人员版)
我真的很困惑,我知道标量函数不是最有效的,但是 运行ning 时间的急剧增加让我感到困惑。
正如我在评论中提到的,您的问题在这里有 2 倍:
- 您有一个 Multi-line 标量函数,众所周知,它通常性能不佳。 (即使您使用 SQL Server 2019,该函数也不会内联。)
- 你的函数中有一个
WHILE
,do 表现不佳,因为 SQL 是一种 set-based 语言,因此不是为了很好地执行迭代过程。
我假设该函数的意图是它执行它调用的操作,并且只保留字符串中的数字和字母。由于您没有注意到版本,因此我建议使用内联 table-value 函数。我将 假设 ,但是,您可以访问足够新的版本来使用 STRING_AGG
不过:
CREATE FUNCTION dbo.RemoveNonAlphaCharacters (@InputString varchar(1000))
RETURNS table
AS RETURN
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT TOP (LEN(@InputString))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
FROM N N1, N N2, N N3),
Chars AS(
SELECT I,
SUBSTRING(@InputString,I,1) AS C
FROM Tally)
SELECT STRING_AGG(C,'') WITHIN GROUP (ORDER BY I) AS OutputString
FROM Chars
WHERE C LIKE '[A-z]'
OR C LIKE '[0-9]';
然后你可以在 FROM
:
CROSS APPLY
调用所述函数
SELECT V.YourString,
RNAC.OutputString
FROM (VALUES('abc 123-789'),('Apples & Pears'),('Mr O''Mally'))V(YourString)
CROSS APPLY dbo.RemoveNonAlphaCharacters(V.YourString) RNAC;
如果您使用的不是最新版本的 SQL 服务器,则需要将 STRING_AGG
调用替换为“旧”FOR XML PATH
(以及 STUFF
) 方法。