1

在 SQL Server 2005 上,我有一个复杂的多级分配过程,如下所示(伪 SQL):

FOR EACH @LVL_NUM < @MAX_LVL:
INSERT INTO ALLOCS
SELECT 'OUT', *
FROM BALANCES(@LVL_NUM)
INNER JOIN ALLOCN_SUMRY(@LVL_NUM)

INSERT INTO ALLOCS
SELECT 'IN', *
FROM BALANCES(@LVL_NUM)
INNER JOIN ALLOCNS(@LVL_NUM)
INNER JOIN ALLOCN_SUMRY(@LVL_NUM)

WhereALLOCS以直接分配为种子,然后BALANCES(@LVL_NUM)基于ALLOCSat @LVL_NUM(可能是一些直接分配加上前一级别的一些 IN 分配),并且ALOCNS(@LVL_NUM)基于BALANCES(@LVL_NUM)并且ALOCN_SUMRY(@LVL_NUM)仅基于ALOCNS(@LVL_NUM)- 有很多配置表,这些配置表指示驱动程序将分配赶出去。

这被简化了,但实际上循环中有四五对这样的对,因为有多种逻辑无法一起处理(有些情况可以一起处理)。

其基本逻辑是在特定成本中心/产品线/等(即)中获取总金额,然后根据其在特定成本中心/产品线/等中的份额(即百分比份额)将BALANCES其分配给另一个成本中心/产品线/等。ALLOCNS / ALLOCN_SUMRY公制。

在记录OUT保存INSUMRY.ALLOCN是一个加号!)。(现有的系统是一个怪物 C/C++/MFC/ODBC 程序,它将所有数据读入海量数组和其他数据结构中,编写得非常糟糕。)

问题似乎是,当在循环中运行时,我似乎遇到了执行计划问题,因为随着ALLOCS表格开始发生变化(并且一切都在变化,因为级别有不同的成本中心,所以配置被用来驱动ALLOCNS正在改变)。我认为我最多有 99 个级别,但最低级别从 2、4、6 开始。似乎@LVL_NUM = 6在 UDF 之外单独运行表现良好,但 UDF 表现不佳 - 可能是因为 UDF 有缓存计划或整体计划已经很糟糕了,因为在ALLOCS前面的步骤中添加了@LVL_NUM IN (2, 4)

在开发早期,我设法在 30 分钟内完成了 30 个关卡,但现在我无法在 2 小时内完成前 3 个关卡。

我正在考虑在另一个 SP 中运行这两个插入并将其称为 WITH RECOMPILE,但很好奇这个 RECOMPILE 是否正确级联到 TVF UDF?任何其他建议也将不胜感激。

真实代码:

/****** Object:  UserDefinedFunction [MISProcess].[udf_MR_BALANCES_STAT_UNI]    Script Date: 05/14/2009 22:16:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [MISProcess].[udf_MR_BALANCES_STAT_UNI] (
     @DATA_DT_ID int
    ,@LVL_NUM int
    )
RETURNS TABLE
--    WITH SCHEMABINDING
AS 
RETURN
    (
     SELECT AB.YYMM_ID
           ,AB.BUS_UNIT_ID
           ,AB.BUS_UNIT_PROD_LINE_CD
--                   ,AB.ALOCN_SRC_CD
           ,AB.ALOCN_SRC_PROD_LINE_CD
           ,CASE WHEN ORIG_ALSRC.ALOCN_TYPE_CD = 'C'
                      AND ORIG_ALSRC.RETN_IND = 'Y' THEN AB.ORIG_ALOCN_SRC_CD
                 ELSE AB.BUS_UNIT_ID
            END AS ORIG_ALOCN_SRC_CD
           ,CASE WHEN BUPALSRC.COLLAPSE_IND = 'Y'
                 THEN BUPLNTM.ALOCN_LINE_ITEM_NUM
                 ELSE AB.LINE_ITEM_NUM
            END AS ALOCN_LINE_ITEM_NUM
           ,SUM(BUPLNTM.ALOCN_SIGN_IND * AB.ANULZD_ACTL_BAL) AS ANULZD_ACTL_BAL
     FROM   MISWork.vwMR_BALANCES AS AB
     INNER JOIN MISProcess.LKP_BUPLNTM AS BUPLNTM
            ON BUPLNTM.DATA_DT_ID = @DATA_DT_ID
               AND BUPLNTM.LINE_ITEM_NUM = AB.LINE_ITEM_NUM
               AND BUPLNTM.ALOCN_LINE_ITEM_NUM <> 0
     INNER JOIN [MISProcess].[udf_MR_ALSRC](@DATA_DT_ID, @LVL_NUM) AS BUPALSRC
            ON BUPALSRC.ALOCN_SRC_CD = AB.BUS_UNIT_ID
     INNER JOIN [MISProcess].LKP_BUPALSRC AS ORIG_ALSRC
            ON ORIG_ALSRC.DATA_DT_ID = @DATA_DT_ID
               AND ORIG_ALSRC.ALOCN_SRC_CD = AB.ORIG_ALOCN_SRC_CD
     GROUP BY AB.YYMM_ID
           ,AB.BUS_UNIT_ID
           ,AB.BUS_UNIT_PROD_LINE_CD
--                   ,AB.ALOCN_SRC_CD
           ,AB.ALOCN_SRC_PROD_LINE_CD
           ,CASE WHEN ORIG_ALSRC.ALOCN_TYPE_CD = 'C'
                      AND ORIG_ALSRC.RETN_IND = 'Y' THEN AB.ORIG_ALOCN_SRC_CD
                 ELSE AB.BUS_UNIT_ID
            END
           ,CASE WHEN BUPALSRC.COLLAPSE_IND = 'Y'
                 THEN BUPLNTM.ALOCN_LINE_ITEM_NUM
                 ELSE AB.LINE_ITEM_NUM
            END
    )

/****** Object:  UserDefinedFunction [MISProcess].[udf_MR_ALOCNS_STAT_UNI]    Script Date: 05/14/2009 22:16:16 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [MISProcess].[udf_MR_ALOCNS_STAT_UNI] (
     @DATA_DT_ID int
    ,@LVL_NUM int
    )
RETURNS TABLE
--    WITH SCHEMABINDING
AS 
RETURN
    (
     SELECT BALANCES.YYMM_ID
           ,BS.ALOCN_SRC_CD AS BUS_UNIT_ID
           ,BS.PROD_LINE_CD AS BUS_UNIT_PROD_LINE_CD
           ,BALANCES.BUS_UNIT_ID AS ALOCN_SRC_CD
           ,BALANCES.BUS_UNIT_PROD_LINE_CD AS ALOCN_SRC_PROD_LINE_CD
           ,BALANCES.ORIG_ALOCN_SRC_CD
           ,BALANCES.ALOCN_LINE_ITEM_NUM
           ,SUM(BS.ACCT_STATS_CNT) AS ACCT_STATS_CNT
     FROM   [MISProcess].[udf_MR_BALANCES_STAT_UNI](@DATA_DT_ID, @LVL_NUM) AS BALANCES
     INNER JOIN [MISProcess].[udf_MR_ALSRC](@DATA_DT_ID, @LVL_NUM) AS BUPALSRC
            ON BUPALSRC.ALOCN_SRC_CD = BALANCES.BUS_UNIT_ID
     INNER JOIN MISProcess.LKP_PRODLINE AS PRODLINE
            ON PRODLINE.DATA_DT_ID = @DATA_DT_ID
               AND PRODLINE.PROD_LINE_CD = BALANCES.BUS_UNIT_PROD_LINE_CD
     INNER JOIN PUASFIN.FocusResults.BS AS BS
            ON BS.YYMM_ID = BALANCES.YYMM_ID
               AND BS.ALOCN_BASE_CD = BUPALSRC.ALOCN_BASE_CD
               AND BS.ALOCN_SRC_CD <> BALANCES.BUS_UNIT_ID
               AND (
                    PRODLINE.GENRC_PROD_LINE_IND = 'Y'
                    OR BS.PROD_LINE_CD = BALANCES.BUS_UNIT_PROD_LINE_CD
                   )
     INNER JOIN [MISProcess].[udf_MR_ALSRC](@DATA_DT_ID, 0) AS DEST_BUP_ALSRC
            ON DEST_BUP_ALSRC.ALOCN_SRC_CD = BS.ALOCN_SRC_CD
               AND DEST_BUP_ALSRC.ALOCN_LVL_NUM > @LVL_NUM
     LEFT JOIN [MISProcess].[udf_MR_BLOCK_STD_COST_PCT](@DATA_DT_ID) AS BLOCK_STD_COST_PCT
            ON BLOCK_STD_COST_PCT.FROM_ALOCN_SRC_CD = BALANCES.BUS_UNIT_ID
     LEFT JOIN [MISProcess].[udf_MR_BLOCK_NOT](@DATA_DT_ID) AS BLOCK_NOT
            ON BLOCK_NOT.ALOCN_SRC_CD = BALANCES.BUS_UNIT_ID
     LEFT JOIN [MISProcess].[udf_MR_BLOCK](@DATA_DT_ID) AS BLOCK
            ON BLOCK_NOT.ALOCN_SRC_CD IS NULL
               AND BLOCK.FROM_ALOCN_SRC_CD = BALANCES.BUS_UNIT_ID
               AND (
                    BLOCK.FROM_PROD_LINE_CD IS NULL
                    OR BLOCK.FROM_PROD_LINE_CD = BALANCES.BUS_UNIT_PROD_LINE_CD
                   )
     LEFT JOIN [MISProcess].[udf_MR_BLOCK_ALOCN_PAIRS](@DATA_DT_ID, @LVL_NUM)
            AS BLOCK_ALOCN_PAIRS
            ON BLOCK_NOT.ALOCN_SRC_CD IS NOT NULL
               AND BLOCK_ALOCN_PAIRS.FROM_ALOCN_SRC_CD = BALANCES.BUS_UNIT_ID
               AND BLOCK_ALOCN_PAIRS.TO_ALOCN_SRC_CD = BS.ALOCN_SRC_CD
     WHERE  BLOCK_ALOCN_PAIRS.TO_ALOCN_SRC_CD IS NULL
            AND BLOCK_STD_COST_PCT.FROM_ALOCN_SRC_CD IS NULL
            AND (
                 BLOCK.TO_ALOCN_SRC_CD IS NULL
                 OR BLOCK.TO_ALOCN_SRC_CD = BS.ALOCN_SRC_CD
                )
            AND (
                 BLOCK.TO_PROD_LINE_CD IS NULL
                 OR BLOCK.TO_PROD_LINE_CD = BS.PROD_LINE_CD
                )
            AND (
                 BLOCK.YEAR_NUM IS NULL
                 OR BLOCK.YEAR_NUM = BALANCES.YYMM_ID / 10000
                )
            AND (
                 BLOCK.MTH_NUM IS NULL
                 OR BLOCK.MTH_NUM = (BALANCES.YYMM_ID / 100) % 100
                )
            AND (
                 BLOCK.TO_DIV_NUM IS NULL
                 OR BLOCK.TO_DIV_NUM = DEST_BUP_ALSRC.DIV_NUM
                )
            AND (
                 BLOCK.TO_GRP_NUM IS NULL
                 OR BLOCK.TO_GRP_NUM = DEST_BUP_ALSRC.DIV_GRP
                )
            AND (
                 BLOCK.TO_REGN_GRP_NM IS NULL
                 OR BLOCK.TO_REGN_GRP_NM = DEST_BUP_ALSRC.REGN_GRP_NM
                )
            AND (
                 BLOCK.TO_REGN_NM IS NULL
                 OR BLOCK.TO_REGN_NM = DEST_BUP_ALSRC.REGN_NM
                )
            AND (
                 BLOCK.TO_ARENA_NM IS NULL
                 OR BLOCK.TO_ARENA_NM = DEST_BUP_ALSRC.ARENA_NM
                )
            AND (
                 BLOCK.TO_SUB_REGN_NM IS NULL
                 OR BLOCK.TO_SUB_REGN_NM = DEST_BUP_ALSRC.SUB_REGN_NM
                )
            AND (
                 BLOCK.TO_SUB_ARENA_NM IS NULL
                 OR BLOCK.TO_SUB_ARENA_NM = DEST_BUP_ALSRC.SUB_ARENA_NM
                )
     GROUP BY BALANCES.YYMM_ID
           ,BS.ALOCN_SRC_CD
           ,BS.PROD_LINE_CD
           ,BALANCES.BUS_UNIT_ID
           ,BALANCES.BUS_UNIT_PROD_LINE_CD
           ,BALANCES.ORIG_ALOCN_SRC_CD
           ,BALANCES.ALOCN_LINE_ITEM_NUM
    )

/****** Object:  UserDefinedFunction [MISProcess].[udf_MR_ALOCN_SUMRY_STAT_UNI]    Script Date: 05/14/2009 22:16:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [MISProcess].[udf_MR_ALOCN_SUMRY_STAT_UNI] (
     @DATA_DT_ID int
    ,@LVL_NUM int
    )
RETURNS TABLE
--    WITH SCHEMABINDING
AS 
RETURN
    (
     SELECT YYMM_ID
           ,ALOCN_SRC_CD
           ,ALOCN_SRC_PROD_LINE_CD
           ,ORIG_ALOCN_SRC_CD
           ,ALOCN_LINE_ITEM_NUM
           ,SUM(ACCT_STATS_CNT) AS ACCT_STATS_CNT
     FROM   [MISProcess].[udf_MR_ALOCNS_STAT_UNI](@DATA_DT_ID, @LVL_NUM) AS ALOCNS
     GROUP BY YYMM_ID
           ,ALOCN_SRC_CD
           ,ALOCN_SRC_PROD_LINE_CD
           ,ORIG_ALOCN_SRC_CD
           ,ALOCN_LINE_ITEM_NUM
    )

这是我的测试批次,最终将在单个 SP 中运行整个过程。您可以从注释掉的部分看到我也一直在使用临时表和表变量:

USE PCAPFIN

DECLARE @DATA_DT_ID_use AS int
DECLARE @MinLevel AS int
DECLARE @MaxLevel AS int
DECLARE @TestEveryLevel AS bit
DECLARE @TestFinal AS bit

SET @DATA_DT_ID_use = 20090331
SET @MinLevel = 6
SET @MaxLevel = 6
SET @TestEveryLevel = 0
SET @TestFinal = 1

--DECLARE @BALANCES TABLE (
--     METHOD_TXT varchar(12) NOT NULL
--    ,YYMM_ID int NOT NULL
--    ,BUS_UNIT_ID varchar(6) NOT NULL
--    ,BUS_UNIT_PROD_LINE_CD varchar(4) NOT NULL
--    ,ALOCN_SRC_PROD_LINE_CD varchar(4) NOT NULL
--    ,ORIG_ALOCN_SRC_CD varchar(6) NOT NULL
--    ,ALOCN_LINE_ITEM_NUM int NOT NULL
--    ,ANULZD_ACTL_BAL money
--    )
--
--DECLARE @ALOCNS TABLE (
--     METHOD_TXT varchar(12) NOT NULL
--    ,YYMM_ID int NOT NULL
--    ,BUS_UNIT_ID varchar(6) NOT NULL
--    ,BUS_UNIT_PROD_LINE_CD varchar(4) NOT NULL
--    ,ALOCN_SRC_CD varchar(6) NOT NULL
--    ,ALOCN_SRC_PROD_LINE_CD varchar(4) NOT NULL
--    ,ORIG_ALOCN_SRC_CD varchar(6) NOT NULL
--    ,ALOCN_LINE_ITEM_NUM int NOT NULL
--    ,ACCT_STATS_CNT money
--    )
--
--DECLARE @ALOCN_SUMRY TABLE (
--     METHOD_TXT varchar(12) NOT NULL
--    ,YYMM_ID int NOT NULL
--    ,ALOCN_SRC_CD varchar(6) NOT NULL
--    ,ALOCN_SRC_PROD_LINE_CD varchar(4) NOT NULL
--    ,ORIG_ALOCN_SRC_CD varchar(6) NOT NULL
--    ,ALOCN_LINE_ITEM_NUM int NOT NULL
--    ,ACCT_STATS_CNT money
--    )

--IF OBJECT_ID('tempdb..#BALANCES') IS NOT NULL 
--    DROP TABLE #BALANCES
--
--CREATE TABLE #BALANCES (
--     METHOD_TXT varchar(12) NOT NULL
--    ,YYMM_ID int NOT NULL
--    ,BUS_UNIT_ID varchar(6) NOT NULL
--    ,BUS_UNIT_PROD_LINE_CD varchar(4) NOT NULL
--    ,ALOCN_SRC_PROD_LINE_CD varchar(4) NOT NULL
--    ,ORIG_ALOCN_SRC_CD varchar(6) NOT NULL
--    ,ALOCN_LINE_ITEM_NUM int NOT NULL
--    ,ANULZD_ACTL_BAL money
--    ,CONSTRAINT [PK_BALANCES] PRIMARY KEY CLUSTERED ([METHOD_TXT] ASC, [YYMM_ID] ASC, [BUS_UNIT_ID] ASC, [BUS_UNIT_PROD_LINE_CD] ASC, [ALOCN_SRC_PROD_LINE_CD] ASC, [ORIG_ALOCN_SRC_CD] ASC, [ALOCN_LINE_ITEM_NUM] ASC)
--        WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
--              IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
--              ALLOW_PAGE_LOCKS = ON)
--    )
--
--IF OBJECT_ID('tempdb..#ALOCN_SUMRY') IS NOT NULL 
--    DROP TABLE #ALOCNS
--
--CREATE TABLE #ALOCNS (
--     METHOD_TXT varchar(12) NOT NULL
--    ,YYMM_ID int NOT NULL
--    ,BUS_UNIT_ID varchar(6) NOT NULL
--    ,BUS_UNIT_PROD_LINE_CD varchar(4) NOT NULL
--    ,ALOCN_SRC_CD varchar(6) NOT NULL
--    ,ALOCN_SRC_PROD_LINE_CD varchar(4) NOT NULL
--    ,ORIG_ALOCN_SRC_CD varchar(6) NOT NULL
--    ,ALOCN_LINE_ITEM_NUM int NOT NULL
--    ,ACCT_STATS_CNT money
--    ,CONSTRAINT [PK_ALOCNS] PRIMARY KEY CLUSTERED ([METHOD_TXT] ASC, YYMM_ID ASC, BUS_UNIT_ID ASC, BUS_UNIT_PROD_LINE_CD ASC, ALOCN_SRC_CD ASC, ALOCN_SRC_PROD_LINE_CD ASC, ORIG_ALOCN_SRC_CD ASC, ALOCN_LINE_ITEM_NUM ASC)
--        WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
--              IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
--              ALLOW_PAGE_LOCKS = ON)
--    )
--
--IF OBJECT_ID('tempdb..#ALOCN_SUMRY') IS NOT NULL 
--    DROP TABLE #ALOCN_SUMRY
--CREATE TABLE #ALOCN_SUMRY (
--     METHOD_TXT varchar(12) NOT NULL
--    ,YYMM_ID int NOT NULL
--    ,ALOCN_SRC_CD varchar(6) NOT NULL
--    ,ALOCN_SRC_PROD_LINE_CD varchar(4) NOT NULL
--    ,ORIG_ALOCN_SRC_CD varchar(6) NOT NULL
--    ,ALOCN_LINE_ITEM_NUM int NOT NULL
--    ,ACCT_STATS_CNT money
--    ,CONSTRAINT [PK_ALOCN_SUMRY] PRIMARY KEY CLUSTERED ([METHOD_TXT] ASC, YYMM_ID ASC, ALOCN_SRC_CD ASC, ALOCN_SRC_PROD_LINE_CD ASC, ORIG_ALOCN_SRC_CD ASC, ALOCN_LINE_ITEM_NUM ASC)
--        WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
--              IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON,
--              ALLOW_PAGE_LOCKS = ON)
--    )

SET @MinLevel = (
                 SELECT MIN(BUPALSRC.ALOCN_LVL_NUM)
                 FROM   MISProcess.LKP_BUPALSRC AS BUPALSRC
                 WHERE  BUPALSRC.DATA_DT_ID = @DATA_DT_ID_use
                        AND BUPALSRC.ALOCN_LVL_NUM >= @MinLevel
                )

DECLARE @Restart AS bit
IF @MinLevel > (
                SELECT  MIN(BUPALSRC.ALOCN_LVL_NUM)
                FROM    MISProcess.LKP_BUPALSRC AS BUPALSRC
                WHERE   BUPALSRC.DATA_DT_ID = @DATA_DT_ID_use
               ) 
    SET @Restart = 0
ELSE 
    SET @Restart = 1

DECLARE @subset_criteria AS varchar(max)

SET NOCOUNT ON

IF @Restart = 1 
    BEGIN
        RAISERROR ('Restarting process', 10, 1) WITH NOWAIT
--        TRUNCATE TABLE MISWork.AB
        DELETE FROM MISWork.AB

        INSERT  INTO MISWork.AB (
                 YYMM_ID
                ,BUS_UNIT_ID
                ,BUS_UNIT_PROD_LINE_CD
                ,ALOCN_SRC_CD
                ,ALOCN_SRC_PROD_LINE_CD
                ,ORIG_ALOCN_SRC_CD
                ,LINE_ITEM_NUM
                ,BAL_ORIGTN_IND
                ,ANULZD_ACTL_BAL
                ,ACCT_STATS_CNT
                ,LVL_NUM
                ,METHOD_TXT
                )
                SELECT  YYMM_ID
                       ,ALOCN_SRC_CD AS BUS_UNIT_ID
                       ,PROD_LINE_CD AS BUS_UNIT_PROD_LINE_CD
                       ,ALOCN_SRC_CD
                       ,PROD_LINE_CD AS ALOCN_SRC_PROD_LINE_CD
                       ,ALOCN_SRC_CD AS ORIG_ALOCN_SRC_CD
                       ,LINE_ITEM_NUM
                       ,'D' AS BAL_ORIGTN_IND
                       ,FIN_ALOCN_AMT AS ANULZD_ACTL_BAL
                       ,0.0 AS ACCT_STATS_CNT
                       ,0 AS LVL_NUM
                       ,'D-INIT' AS METHOD_TXT
    --        FROM    MISProcess.FIN_FTP
                FROM    PUASFIN.FocusResults.BUPALLGE
    END
ELSE 
    BEGIN
        DELETE  FROM MISWork.AB
        WHERE   LVL_NUM >= @MinLevel
    END

DECLARE @LVL_NUM AS int
SET @LVL_NUM = @MinLevel
WHILE @LVL_NUM <= @MaxLevel
    BEGIN
        DECLARE @LevelStart AS varchar(50)
        SET @LevelStart = 'Level:' + CONVERT(varchar, @LVL_NUM)
        RAISERROR (@LevelStart, 10, 1) WITH NOWAIT

        RAISERROR ('STD_COST_PCT allocations - No D - B records', 10, 1) WITH NOWAIT
        -- STD_COST_PCT allocations - No D - B records
        INSERT  INTO MISWork.AB (
                 YYMM_ID
                ,BUS_UNIT_ID
                ,BUS_UNIT_PROD_LINE_CD
                ,ALOCN_SRC_CD
                ,ALOCN_SRC_PROD_LINE_CD
                ,ORIG_ALOCN_SRC_CD
                ,LINE_ITEM_NUM
                ,BAL_ORIGTN_IND
                ,ANULZD_ACTL_BAL
                ,ACCT_STATS_CNT
                ,LVL_NUM
                ,METHOD_TXT
                )
                SELECT  ALOCNS.YYMM_ID
                       ,ALOCNS.BUS_UNIT_ID
                       ,ALOCNS.BUS_UNIT_PROD_LINE_CD
                       ,ALOCNS.BUS_UNIT_ID AS ALOCN_SRC_CD
                       ,ALOCNS.BUS_UNIT_PROD_LINE_CD AS ALOCN_SRC_PROD_LINE_CD
                       ,ALOCNS.BUS_UNIT_ID AS ORIG_ALOCN_SRC_CD
                       ,ALOCNS.LINE_ITEM_NUM
                       ,'B' AS BAL_ORIGTN_IND
                       ,-1.0 * ROUND(ALOCNS.ANULZD_ACTL_BAL, 2) AS ANULZD_ACTL_BAL
                       ,ROUND(ALOCNS.ACCT_STATS_CNT, 2) AS ACCT_STATS_CNT
                       ,@LVL_NUM AS LVL_NUM
                       ,'NO-D-B' AS METHOD_TXT
                FROM    [MISProcess].[udf_MR_ALOCNS_STD_COST_PCT_NO_D](@DATA_DT_ID_use, @LVL_NUM)
                        AS ALOCNS

        RAISERROR ('STD_COST_PCT allocations - No D - A records', 10, 1) WITH NOWAIT
        -- STD_COST_PCT allocations - No D - A records
        INSERT  INTO MISWork.AB (
                 YYMM_ID
                ,BUS_UNIT_ID
                ,BUS_UNIT_PROD_LINE_CD
                ,ALOCN_SRC_CD
                ,ALOCN_SRC_PROD_LINE_CD
                ,ORIG_ALOCN_SRC_CD
                ,LINE_ITEM_NUM
                ,BAL_ORIGTN_IND
                ,ANULZD_ACTL_BAL
                ,ACCT_STATS_CNT
                ,LVL_NUM
                ,METHOD_TXT
                )
                SELECT  ALOCNS.YYMM_ID
                       ,BLOCK.TO_ALOCN_SRC_CD AS BUS_UNIT_ID
                       ,ALOCNS.ALOCN_SRC_PROD_LINE_CD AS BUS_UNIT_PROD_LINE_CD
                       ,ALOCNS.ALOCN_SRC_CD
                       ,ALOCNS.BUS_UNIT_PROD_LINE_CD AS ALOCN_SRC_PROD_LINE_CD
                       ,ALOCNS.ORIG_ALOCN_SRC_CD
                       ,ALOCNS.LINE_ITEM_NUM
                       ,'A' AS BAL_ORIGTN_IND
                       ,ROUND(ALOCNS.ANULZD_ACTL_BAL, 2) AS ANULZD_ACTL_BAL
                       ,ROUND(ALOCNS.ACCT_STATS_CNT, 2) AS ACCT_STATS_CNT
                       ,@LVL_NUM AS LVL_NUM
                       ,'NO-D-A' AS METHOD_TXT
                FROM    [MISProcess].[udf_MR_ALOCNS_STD_COST_PCT_NO_D](@DATA_DT_ID_use, @LVL_NUM)
                        AS ALOCNS
                INNER JOIN MISProcess.LKP_BLOCK AS BLOCK
                        -- TODO: Can this be moved into the udf above?
                            ON BLOCK.DATA_DT_ID = @DATA_DT_ID_use
                               AND BLOCK.FROM_ALOCN_SRC_CD = ALOCNS.BUS_UNIT_ID

        RAISERROR ('STD_COST_PCT allocations - B records', 10, 1) WITH NOWAIT

        -- STD_COST_PCT allocations - B records
        INSERT  INTO MISWork.AB (
                 YYMM_ID
                ,BUS_UNIT_ID
                ,BUS_UNIT_PROD_LINE_CD
                ,ALOCN_SRC_CD
                ,ALOCN_SRC_PROD_LINE_CD
                ,ORIG_ALOCN_SRC_CD
                ,LINE_ITEM_NUM
                ,BAL_ORIGTN_IND
                ,ANULZD_ACTL_BAL
                ,ACCT_STATS_CNT
                ,LVL_NUM
                ,METHOD_TXT
                )
                SELECT  ALOCNS.YYMM_ID
                       ,ALOCNS.BUS_UNIT_ID
                       ,ALOCNS.BUS_UNIT_PROD_LINE_CD
                       ,ALOCNS.ALOCN_SRC_CD
                       ,ALOCNS.BUS_UNIT_PROD_LINE_CD AS ALOCN_SRC_PROD_LINE_CD
                       ,ALOCNS.ORIG_ALOCN_SRC_CD
                       ,ALOCNS.LINE_ITEM_NUM
                       ,'B' AS BAL_ORIGTN_IND
                       ,-1.0 * ROUND(ALOCNS.ANULZD_ACTL_BAL * RATIOS.RATIO, 2) AS ANULZD_ACTL_BAL
                       ,ROUND(ALOCNS.ACCT_STATS_CNT, 2) AS ACCT_STATS_CNT
                       ,@LVL_NUM AS LVL_NUM
                       ,'STD-B' AS METHOD_TXT
                FROM    [MISProcess].[udf_MR_ALOCNS_STD_COST_PCT](@DATA_DT_ID_use, @LVL_NUM)
                        AS ALOCNS
                INNER JOIN [MISProcess].[udf_MR_RATIOS_STD_COST_PCT](@DATA_DT_ID_use, @LVL_NUM)
                        AS RATIOS
                        ON RATIOS.YYMM_ID = ALOCNS.YYMM_ID
                           AND RATIOS.BUS_UNIT_ID = ALOCNS.BUS_UNIT_ID
                           AND RATIOS.LINE_ITEM_NUM = ALOCNS.LINE_ITEM_NUM

        RAISERROR ('STD_COST_PCT allocations - A records', 10, 1) WITH NOWAIT

        -- STD_COST_PCT allocations - A records
        ;
        WITH    CORRECTED_ALOCNS
                  AS (
                      SELECT    ALOCNS.YYMM_ID
                               ,ALOCNS.BUS_UNIT_ID
                               ,ALOCNS.BUS_UNIT_PROD_LINE_CD
                               ,ALOCNS.ALOCN_SRC_CD
                               ,ALOCNS.ALOCN_SRC_PROD_LINE_CD
                               ,ALOCNS.ORIG_ALOCN_SRC_CD
                               ,ALOCNS.LINE_ITEM_NUM
                               ,ALOCNS.ANULZD_ACTL_BAL * RATIOS.RATIO AS ANULZD_ACTL_BAL
                               ,CASE WHEN RATIOS.RATIO <> 1.0
                                     THEN RATIOS.RATIO
                                     ELSE ALOCNS.ACCT_STATS_CNT
                                END AS ACCT_STATS_CNT
                      FROM      [MISProcess].[udf_MR_CORR_ALOCNS_STD_COST_PCT](@DATA_DT_ID_use, @LVL_NUM)
                                AS ALOCNS
                      INNER JOIN [MISProcess].[udf_MR_RATIOS_STD_COST_PCT](@DATA_DT_ID_use, @LVL_NUM)
                                AS RATIOS
                                ON RATIOS.YYMM_ID = ALOCNS.YYMM_ID
                                   AND RATIOS.BUS_UNIT_ID = ALOCNS.ALOCN_SRC_CD
                                   AND RATIOS.LINE_ITEM_NUM = ALOCNS.LINE_ITEM_NUM
                     ),
                ROUNDED_ALOCNS
                  AS (
                      SELECT    YYMM_ID
                               ,BUS_UNIT_ID
                               ,BUS_UNIT_PROD_LINE_CD
                               ,ALOCN_SRC_CD
                               ,ALOCN_SRC_PROD_LINE_CD
                               ,ORIG_ALOCN_SRC_CD
                               ,LINE_ITEM_NUM
                               ,CASE WHEN ABS(ANULZD_ACTL_BAL) < 0.05 THEN 0.0
                                     WHEN ABS(ANULZD_ACTL_BAL) > 0.05
                                          AND ABS(ANULZD_ACTL_BAL) < 0.10
                                     THEN 0.10 * SIGN(ANULZD_ACTL_BAL)
                                     ELSE ANULZD_ACTL_BAL
                                END AS ANULZD_ACTL_BAL
                               ,ACCT_STATS_CNT
                      FROM      CORRECTED_ALOCNS
                     )
            INSERT  INTO MISWork.AB (
                     YYMM_ID
                    ,BUS_UNIT_ID
                    ,BUS_UNIT_PROD_LINE_CD
                    ,ALOCN_SRC_CD
                    ,ALOCN_SRC_PROD_LINE_CD
                    ,ORIG_ALOCN_SRC_CD
                    ,LINE_ITEM_NUM
                    ,BAL_ORIGTN_IND
                    ,ANULZD_ACTL_BAL
                    ,ACCT_STATS_CNT
                    ,LVL_NUM
                    ,METHOD_TXT
                    )
                    SELECT  YYMM_ID
                           ,BUS_UNIT_ID
                           ,BUS_UNIT_PROD_LINE_CD
                           ,ALOCN_SRC_CD
                           ,ALOCN_SRC_PROD_LINE_CD
                           ,ORIG_ALOCN_SRC_CD
                           ,LINE_ITEM_NUM
                           ,'A' AS BAL_ORIGTN_IND
                           ,ROUND(ANULZD_ACTL_BAL, 2) AS ANULZD_ACTL_BAL
                           ,ROUND(ACCT_STATS_CNT, 2) AS ACCT_STATS_CNT
                           ,@LVL_NUM AS LVL_NUM
                           ,'STD-A' AS METHOD_TXT
                    FROM    ROUNDED_ALOCNS
                    WHERE   ANULZD_ACTL_BAL <> 0.0
                            OR ACCT_STATS_CNT <> 0.0

        RAISERROR ('COLLAPSE, BLOCK 100 ALOCN_PCT - B records', 10, 1) WITH NOWAIT

        -- COLLAPSE, BLOCK 100% ALOCN_PCT - B records
        INSERT  INTO MISWork.AB (
                 YYMM_ID
                ,BUS_UNIT_ID
                ,BUS_UNIT_PROD_LINE_CD
                ,ALOCN_SRC_CD
                ,ALOCN_SRC_PROD_LINE_CD
                ,ORIG_ALOCN_SRC_CD
                ,LINE_ITEM_NUM
                ,BAL_ORIGTN_IND
                ,ANULZD_ACTL_BAL
                ,ACCT_STATS_CNT
                ,LVL_NUM
                ,METHOD_TXT
                )
                SELECT  BALANCES.YYMM_ID
                       ,BALANCES.BUS_UNIT_ID
                       ,BALANCES.BUS_UNIT_PROD_LINE_CD
                       ,BALANCES.BUS_UNIT_ID AS ALOCN_SRC_CD
                       ,BALANCES.BUS_UNIT_PROD_LINE_CD AS ALOCN_SRC_PROD_LINE_CD
                       ,BALANCES.ORIG_ALOCN_SRC_CD
                       ,BALANCES.ALOCN_LINE_ITEM_NUM AS LINE_ITEM_NUM
                       ,'B' AS BAL_ORIGTN_IND
                       ,-1.0 * BALANCES.ANULZD_ACTL_BAL
                       ,ALOCN_SUMRY.ACCT_STATS_CNT
                       ,@LVL_NUM AS LVL_NUM
                       ,'BLOCK-100' AS METHOD_TXT
                FROM    [MISProcess].[udf_MR_BALANCES_BLOCK_100_PCT](@DATA_DT_ID_use, @LVL_NUM)
                        AS BALANCES
                INNER JOIN [MISProcess].[udf_MR_ALOCN_SUMRY_BLOCK_100_PCT](@DATA_DT_ID_use, @LVL_NUM)
                        AS ALOCN_SUMRY
                        ON ALOCN_SUMRY.YYMM_ID = BALANCES.YYMM_ID
                           AND ALOCN_SUMRY.BUS_UNIT_ID = BALANCES.BUS_UNIT_ID
                           AND ALOCN_SUMRY.BUS_UNIT_PROD_LINE_CD = BALANCES.BUS_UNIT_PROD_LINE_CD
                           AND ALOCN_SUMRY.ALOCN_SRC_CD = BALANCES.ALOCN_SRC_CD
                           AND ALOCN_SUMRY.ALOCN_SRC_PROD_LINE_CD = BALANCES.ALOCN_SRC_PROD_LINE_CD
                           AND ALOCN_SUMRY.ORIG_ALOCN_SRC_CD = BALANCES.ORIG_ALOCN_SRC_CD

        RAISERROR ('COLLAPSE, BLOCK 100 ALOCN_PCT - A records', 10, 1) WITH NOWAIT

        -- COLLAPSE, BLOCK 100% ALOCN_PCT - A records
        INSERT  INTO MISWork.AB (
                 YYMM_ID
                ,BUS_UNIT_ID
                ,BUS_UNIT_PROD_LINE_CD
                ,ALOCN_SRC_CD
                ,ALOCN_SRC_PROD_LINE_CD
4

3 回答 3

1

是的,重新编译应该扩展到 TV UDFS。

但是,我会使用参数掩码而不是 RECOMPILE。

  1. 使用这样的查询,编译会很昂贵
  2. 当 UDF 未嵌套时,参数掩码也将应用。TV UDF 没有这样的计划:它们是调用查询的一部分,因为它们是非嵌套的。

您可以将一些 UDF 调用分解为临时表,然后加入临时表吗?我敢打赌,当 UDF 未嵌套时,查询太复杂而无法有效运行。优化者可能需要一周的时间才能找到包含如此复杂事物的理想计划。使用临时表(不是表变量),我想你会得到可观的改进。

我自己在一些更大的查询中使用了这种技术(为金融工具生成定价树)

你 150,000 行的事实被我认为的绝对复杂性所掩盖。

编辑

TVF 不需要参数屏蔽,因为它们只是宏。您可以从字面上用 CTE 或派生表替换它。

在这里查看我的答案:查询计划优化器是否适用于连接/过滤的表值函数Tony Rogerson on Views

于 2009-05-15T04:28:03.427 回答
0

使用表值函数(尤其是多语句表值函数)要注意的一件事是生成的表,就像表变量一样,没有列统计信息和索引。

我倾向于谨慎使用 TVF。

于 2009-05-15T02:50:34.050 回答
0

你能发布实际的 T-SQL 而不是伪 SQL 吗?您所描述的听起来像是随着@LVL_NUM 的增加而对越来越大的结果集进行表扫描,并且可能 RECOMPILE 在那里无济于事。但是,基于伪SQL,除了伪猜测之外真的很难给出任何东西......

于 2009-05-15T03:11:18.150 回答