Sql server 当保存为内联表值函数时,T-SQL代码的速度非常慢

Sql server 当保存为内联表值函数时,T-SQL代码的速度非常慢,sql-server,tsql,user-defined-functions,database-performance,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 (

我似乎不明白为什么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')

有什么想法吗?

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

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


如果你打开了统计数据的自动更新功能,那么你很可能会在这里遇到问题,因为初学者
(lower(users.auth_login)=ad.ad_name
不是SARGableNice!不熟悉SARG,信息很好。我已经删除了lower()函数和我仍然有相同的问题。事实上,我已经将逻辑分离到一个视图中,删除了聚合部分,并且我可以对视图进行聚合工作。但是,再次,如果我将该视图包装到一个函数中,我会遇到同样的问题…你可以发布内联和非内联执行计划吗?估计的计划可以吗?我想不会ITVF需要几个小时。当我上次做估计计划时,我得到了一个“缺失指数”关于ITVF和原始代码的良好结果。我会马上发布它们。奇怪的是,我刚刚重新创建了函数来测试它,它在4秒钟内执行!可能有一个DBA修改了一些东西…现在很难识别问题!哇,从来不会猜到。很好的信息!我一获得声誉就会投票!