【问题标题】:How can a stored procedure calling a TVF be slower than a procedure that inlines the TVF?调用 TVF 的存储过程如何比内联 TVF 的过程慢?
【发布时间】:2011-08-31 13:45:43
【问题描述】:

问题:

我有两种看法:

V_Room, 14969 rows, 9 tables joined together
V_parkings, 3265 rows, 9 tables joined together

那我有一个看法

V_Rooms_UsageTypes with 18234 rows

这是 V_Room 和 V_parkings 之间的联合

然后我有一个像这样的表值函数 功能

CREATE FUNCTION [dbo].[tfu_RPT_UsageTypesBySIADetail]
(@in_reporting_date datetime)
-- Add the parameters for the function here
RETURNS TABLE

连接 9 个表 并在视图 V_Rooms_UsageTypes 上进行 77 个子选择,如下所示

(
        SELECT 
            ISNULL(SUM(ZO_RMArea_Area), 0.0) 
        FROM dbo.V_Rooms_UsageTypes 
        WHERE V_Rooms_UsageTypes.FL_UID = T_Floor.FL_UID 

        AND (V_Rooms_UsageTypes.DIN277_Major = 9) 
        AND (V_Rooms_UsageTypes.DIN277_Minor = 4) 

        AND (V_Rooms_UsageTypes.ZO_RMUT_DateFrom <= @in_reporting_date) 
        AND (V_Rooms_UsageTypes.ZO_RMUT_DatumTo >= @in_reporting_date) 

        AND (V_Rooms_UsageTypes.ZO_RMArea_DateFrom <= @in_reporting_date) 
        AND (V_Rooms_UsageTypes.ZO_RMArea_DatumTo >= @in_reporting_date) 

        AND (V_Rooms_UsageTypes.RM_DateFrom <= @in_reporting_date) 
        AND (V_Rooms_UsageTypes.RM_DatumTo >= @in_reporting_date) 

        AND (V_Rooms_UsageTypes.SO_DateFrom <= @in_reporting_date) 
        AND (V_Rooms_UsageTypes.SO_DatumTo >= @in_reporting_date) 

        AND (V_Rooms_UsageTypes.BG_DateFrom <= @in_reporting_date) 
        AND (V_Rooms_UsageTypes.BG_DatumTo >= @in_reporting_date) 

        AND (V_Rooms_UsageTypes.FL_DateFrom <= @in_reporting_date) 
        AND (V_Rooms_UsageTypes.FL_DatumTo >= @in_reporting_date) 
    ) AS RPT_VF_9_4 

然后我有一个调用表值函数的存储过程 使用动态 SQL(因为报告服务的多种语言的列别名, 只需要一个一致的列名)

像这样:

CREATE PROCEDURE [dbo].[sp_RPT_DATA_AreaByDIN277_old]
    @in_customer varchar(3),
    @in_language varchar(2),
    @in_site varchar(36),
    @in_building varchar(36),
    @in_floor varchar(36),
    @in_reporting_date varchar(50)
AS
    DECLARE
    @sql varchar(8000),
    @reporting_date datetime

    -- Abrunden des Eingabedatums auf 00:00:00 Uhr
    SET @reporting_date= CONVERT( DATETIME, @in_reporting_date ) 
    SET @reporting_date= Cast(Floor(Cast(@reporting_date As Float)) As DateTime)
    SET @in_reporting_date= CONVERT(varchar(50), @reporting_date ) 

    SET NOCOUNT ON;



    SET @sql='SELECT  

     FIELD_1_' + @in_language +' AS RPT_FIELD_1
    ,FIELD_2_' + @in_language +' AS RPT_FIELD_2
    ,FIELD_3 AS RPT_FIELD_3 
    ,table_valued_function_column1 AS RPT_table_valued_function_column1
    ,table_valued_function_column2 AS RPT_table_valued_function_column2
    ,table_valued_function_columnN AS RPT_table_valued_function_columnN 

    '



    SET @sql=@sql + 'FROM dbo.tfu_RPT_FM_NutzungsartenNachSIADetail(''' + @in_reporting_date + ''') '

    SET @sql=@sql + 'WHERE ST_Customer = ''' + @in_customer + ''' '


    IF @in_site     <> '00000000-0000-0000-0000-000000000000' SET @sql=@sql + 'AND (ST_UID = ''' + @in_site + ''') '
    IF @in_building <> '00000000-0000-0000-0000-000000000000' SET @sql=@sql + 'AND (BG_UID = ''' + @in_building + ''') '
    IF @in_floor    <> '00000000-0000-0000-0000-000000000000' SET @sql=@sql + 'AND (FL_UID = ''' + @in_floor + ''') '   

    EXECUTE (@sql) 

现在,正如预期的那样,查询返回结果需要相当长的时间(20 秒)。 所以我把整个表值函数移到了动态sql存储过程中 并且执行速度大约为一半 (10s)。

相反,我得到了 30 秒的执行时间。 这是为什么呢?

【问题讨论】:

  • 比较执行计划告诉你什么?
  • 是 EAV 系统吗?此外,具有功能的视图视图也没有通过我的气味测试。你能剪切/粘贴一个没有视图或函数的一次性查询并运行它以查看它有多快。

标签: sql sql-server sql-server-2008 stored-procedures dynamic-sql


【解决方案1】:

很可能引擎可以更好地处理单独优化 TVF,而不是它只是更大查询的一部分。此外,动态 SQL 可能会改变计划的缓存方式。您忘记提及您使用的是哪个版本的 SQL Server,但您是否使用过“optimize for ad hoc workloads”设置或OPTIMIZE FOR UNKNOWN??

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    • 2021-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多