【问题标题】:Scalar-values function in select making a huge difference in performance标量值函数在选择中产生巨大的性能差异
【发布时间】:2016-09-15 19:36:56
【问题描述】:

我使用的是 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 条记录,但只需要一半的时间。从执行计划中可以看出,代价是一样的,并且不涉及并行性。是什么导致了巨大的差异?先感谢您。

【问题讨论】:

标签: sql sql-server-2008 sqlperformance


【解决方案1】:

如果可能,应该避免使用标量函数...

如果您将函数更改为 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;

【讨论】:

    【解决方案2】:

    (你能包含函数的代码吗?)

    如果它是 SELECT &lt;return&gt; FROM table WHERE cols = @params,那么您将针对返回的每一行运行一次该查询,并且您最好跳过该函数并仅将表作为连接添加到您的主查询中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-21
      • 2010-10-15
      • 1970-01-01
      • 2013-02-18
      • 1970-01-01
      • 1970-01-01
      • 2013-05-21
      • 2019-03-26
      相关资源
      最近更新 更多