我正在使用SQL Server 2008.我有一个标量值函数来获取客户端的时区并输出日期时间作为客户端时区。我在存储过程的select语句中使用它。我注意到使用或不使用函数会对性能产生巨大影响,我尝试检查执行计划并使用“统计时间,IO打开”运行存储过程来检查是什么产生了影响。
例如,这是带有时区调整的查询:
Declare @ClientID int
Select @ClientID = 123
select
abt.someID, myDB..adjustTimeZone(@ClientID, abt.dtDate)
from
aBigTable as abt
where
abt.dtDate > '2016-08-01'
and abt.dtDate < '2016-08-30'
以上代码将返回大约16k记录并需要16秒才能完成。
我将记录克隆到九月只是为了确保它不是因为任何缓存,然后我用另一种方式调整时区,如下面的查询:
Declare @ClientID int, @ZoneHourChange int
select @ClientID = 123
select @ZoneHourChange = (select hourOffSet from Client
where ClientID = @ClientID)
select
abt.someID, DateADD(hour, @ZoneHourChange, abt.dtDate)
from
aBigTable as abt
where
abt.dtDate > '2016-09-01'
and abt.dtDate < '2016-09-30'
上面的代码也会返回16k记录,但只需要一半的时间。我可以从执行计划中看出,成本是相同的,并且没有涉及并行性。是什么导致了巨大的差异?先感谢您。
答案 0 :(得分:0)
如果可能的话,标量函数是应该避免的......
如果您将函数更改为inline TVF
返回一个包含一列的表格,那么它可以极大地加快您的查询速度。
试试这个:两个函数看起来都是一样的,但是内联TVF的表现要好得多......
CREATE FUNCTION dbo.TestScalar()
RETURNS VARCHAR(100)
AS
BEGIN
RETURN 'test';
END
GO
CREATE FUNCTION dbo.TestInlineTVF()
RETURNS TABLE
AS
RETURN SELECT 'test' AS Result;
GO
SELECT dbo.TestScalar();
SELECT Result FROM TestInlineTVF();
GO
DROP FUNCTION dbo.TestInlineTVF;
DROP FUNCTION dbo.TestScalar;
答案 1 :(得分:0)
(可以包含该功能的代码吗?)
如果它是SELECT <return> FROM table WHERE cols = @params
,那么你为返回的每一行运行一次查询,你可能最好不要跳过该函数,只是将表作为连接添加到主查询中。 / p>