保存为内联表值函数时,T-SQL代码非常慢

时间:2012-04-04 19:17:05

标签: sql-server tsql user-defined-functions database-performance

我似乎无法弄清楚为什么SQL Server在将我的代码包装在ITVF中时采用完全不同的执行计划。在ITVF内部运行代码时,查询将在5秒内运行。如果我将其保存为ITVF,它将运行20分钟而不会产生结果。我更喜欢在ITVF中使用它来进行代码重用。将代码保存为ITVF的任何想法都会导致严重的性能问题吗?

CREATE FUNCTION myfunction
(
    @start_date date, 
    @stop_date date
)
RETURNS TABLE 
AS
RETURN 
(
    with
    ad as (
        select [START_DATE]
              ,[STOP_DATE]
              ,ID
              ,NAME
              ,'domain1\' + lower(DOMAIN1_NAME)
               collate database_default as ad_name
        from EMP_INFO
        where DOMAIN1_NAME != ''
        union
        select [START_DATE]
              ,[STOP_DATE]
              ,ID
              ,NAME
              ,'domain2\' + lower(DOMAIN2_NAME)
               collate database_default as ad_name
        from EMP_INFO
        where DOMAIN2_NAME != ''
    )
    select ad.ID
          ,ad.NAME
          ,COUNT(*) as MONITORS
    from scores
    join users
        on (scores.evaluator_id = users.[user_id])
    join ad
        on (lower(users.auth_login) = ad.ad_name and
            scores.[start_date] between ad.[START_DATE] and ad.[STOP_DATE])
    where scores.[start_date] between @start_date and @stop_date
    group by ad.ID
            ,ad.NAME
)

编辑:

好的......我想我发现了问题......但我不明白。可能我应该发一个全新的问题,让我知道你的想法。这里的问题是当我用文字调用函数时,它真的很慢......当我用变量调用它时它很快。

-- Executes in about 3 seconds
declare @start_date date = '2012-03-01';
declare @stop_date date = '2012-03-31';
select *
from myfunction(@start_date, @stop_date);

--Takes forever!  Never completes execution...
select *
from myfunction('2012-03-01', '2012-03-31')

有什么想法吗?

1 个答案:

答案 0 :(得分:5)

使用文字时,SQL Server可以查看列统计信息以估计将返回的行数,并根据该假设选择适当的计划。当你使用变量时,在编译时不知道这些值,所以它会回到猜测上。

如果计划在猜测时比引用实际统计数据时更好,那么这表明统计数据可能需要更新。

如果您已启用统计信息的自动更新,那么您可能会遇到此问题Statistics, row estimations and the ascending date column