8

我似乎无法弄清楚为什么 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')

有任何想法吗?

4

1 回答 1

8

当您使用文字时,SQL Server 可以查看列统计信息以估计将返回多少行并根据该假设选择适当的计划。当您使用变量时,这些值在编译时是未知的,因此它依赖于猜测。

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

如果您打开了统计信息的自动更新,那么您很可能会在这里遇到问题统计信息、行估计和升序日期列

于 2012-04-06T21:39:57.363 回答