我最近审核了一位同事的SQL Server函数(在SQL Server 2008
中),他在标量用户定义函数中放置了T-SQL
查询。然后在查询的Select子句中使用该函数。
我认为在函数内部进行查询会产生糟糕的性能,因为我假设返回的每一行都必须运行查询 - 即使该查询已经过优化以查询索引。
以下是我所谈论的一个例子:
create table [PERSON] (
ID int primary key,
FIRSTNAME NVARCHAR(100),
MIDDLENAME NVARCHAR(100) null,
LASTNAME NVARCHAR(100))
GO
INSERT INTO PERSON (ID, FIRSTNAME, MIDDLENAME, LASTNAME)
VALUES (1, 'BOB', 'M', 'BLUE')
INSERT INTO PERSON (ID, FIRSTNAME, MIDDLENAME, LASTNAME)
VALUES (2, 'VALERIE', 'J', 'GREEN')
INSERT INTO PERSON (ID, FIRSTNAME, MIDDLENAME, LASTNAME)
VALUES (3, 'SIMON', 'D', 'RED')
INSERT INTO PERSON (ID, FIRSTNAME, MIDDLENAME, LASTNAME)
VALUES (4, 'LIONEL', 'W', 'BROWN')
GO
-- Scalar Function with T-SQL
CREATE FUNCTION dbo.fn_FormatNameFromId(
@pnPersonId int
)
Returns nvarchar(300)
AS
Begin
return (Select FIRSTNAME + ' ' + MIDDLENAME + ' ' + LASTNAME
From PERSON
Where ID = @pnPersonId)
End
go
-- Scalar Function without T-SQL
CREATE FUNCTION dbo.fn_FormatNameFromValues(
@psFirstName nvarchar(100),
@psMiddleName nvarchar(100),
@psLastName nvarchar(100)
)
Returns nvarchar(300)
AS
Begin
return (@psFirstName + ' ' + @psMiddleName + ' ' + @psLastName)
End
go
-- T-SQL within function
select dbo.fn_FormatNameFromId(ID)
from PERSON
-- Pass values directly
select dbo.fn_FormatNameFromValues(FIRSTNAME, MIDDLENAME, LASTNAME)
FROM PERSON
当比较这两个选项的执行计划时,我发现两个函数的cpu或内存性能没有差别。即使在扩展测试以返回数万行时,也没有性能差异。
有人可以解释fn_FormatNameFromId
不会导致性能下降的原因或原因吗?
答案 0 :(得分:1)
就个人而言,我不是t-sql函数的忠实粉丝,所以我在SQL SERVER中尽可能地避免使用它们,
是的,我知道用户函数在编程方面有很多优点。
直接回答您的问题
当比较这两个选择的执行计划时,我可以 发现两者的CPU或内存性能没有差别 功能
我通常不会比较执行计划,以检查哪个计划更好,哪个更糟糕,因为这些成本仅基于估算值。
任何人都可以解释fn_FormatNameFromId不会导致的原因或原因 失去表现?
因为你还在处理很少的数据我测试了你的两个函数如下:
declare @a int=1
Declare @name varchar(50)
while (@a<99999)
Begin
-- T-SQL within function
select @name = dbo.fn_FormatNameFromId(ID)
from PERSON
SET @a =@a+1
END
它在我的本地系统上运行了13秒
declare @a int=1
Declare @name varchar(50)
while (@a<99999)
Begin
-- Pass values directly
select @name =dbo.fn_FormatNameFromValues(FIRSTNAME, MIDDLENAME, LASTNAME)
FROM PERSON
SET @a =@a+1
END
它在我的本地系统上运行了9秒
啊,我说我不喜欢功能,所以没有功能运行
declare @a int=1
Declare @name varchar(50)
while (@a<99999)
Begin
-- Pass values directly
Select @name= FIRSTNAME + ' ' + MIDDLENAME + ' ' + LASTNAME
From PERSON
SET @a =@a+1
END
并且在我的系统中以2秒钟的速度运行
请阅读以下文章
T-SQL User-Defined Functions: the good, the bad, and the ugly
答案 1 :(得分:1)