1

SQL Server 2005の上で、私はこの(擬似-SQL)のように見える複雑なマルチレベルの割り当てプロセスを持っている:T-SQLプロセスの設計と実行計画(UDFパラメータスニッフィング?)

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) 

ALLOCSBALANCES(@LVL_NUM)ALLOCS@LVL_NUM(一部の直接配分にも前のレベルからのIN配分でもよい)に基づいており、ALOCNS(@LVL_NUM)BALANCES(@LVL_NUM)ALOCN_SUMRY(@LVL_NUM)は単純にALOCNS(@LVL_NUM)に基づいており、多くの設定で割り当てを駆動するドライバを示すテーブル。

これを簡略化するが、一緒に扱うことは不可能である論理の種々存在するため、ループ内のこのような四、五対が実際に存在している(と一緒に扱うことが可能であるいくつかの場合には。)

基本的な論理(すなわちALLOCNS/ALLOCN_SUMRYパーセンテージシェア)(すなわちBALANCES)などの/特定のコストセンタ/製品ラインで合計を取ると、その共有に基づくなど、別の原価センタ/製品ライン/にそれを割り当てることです特定の指標の

そんなに OUT記帳に繰り返しロジックと IN、そしてもちろん、私はかなりよく実行するように見えるインラインテーブル値関数を使用して実装することになった ALLOCN詳細に基づいて SUMRY

(と彼らが一致し、既存の回帰テストでのシステムの動作はプラスです)。 (既存のシステムは、すべてのデータを大規模な配列やその他のデータ構造に読み込み、かなりひどく書かれたモンスターC/C++/MFC/ODBCプログラムです)。

問題は、ループI ALLOCSテーブルの変更が始まり(レベルによってコストセンターが異なるため、すべてが変更されているため、ALLOCNSを駆動するための設定が変更されているため)、実行計画の問題が発生しているようです。私は99のレベルまで持って、私は思いますが、最低レベルは2を開始し、4、6 UDFの外にそれ自体で@LVL_NUM = 6を実行すると、罰金行っていることが、UDFが悪い実行ように見える - UDFは、キャッシュされた計画を持っているので、おそらくまたは前のステップからALLOCSが追加されたため、全体計画がすでに悪いとしていることがあります。@LVL_NUM IN (2, 4)

以前の開発で、私は30分で実行する30個のレベルを得ることができたが、今私はそれが2時間で最初の3つのレベルを完了するために取得することはできません。

私は別のSPの中に2つの挿入を実行している考慮し、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 
+0

を私はSOの質問サイズの上限に走ったように見えたので、私が与えたのUDFの特定のマッチしたセットに、実際のコールが欠落しているが、通話表示されているものに似ています。 –

答えて

1

はい、再コンパイルはTV UDFSに拡張する必要があります。

ただし、RECOMPILEではなくパラメータマスキングを使用します。このようなクエリでは

  1. 、complationはUDFのがネスト解除された場合、パラメータマスキングがあまりにも適用されます
  2. 高価になるだろう。 TV UDFには計画がありません。これらは呼び出されていないため、呼び出し元の問合せの一部です。

一時テーブルにいくつかのUDF呼び出しを分割してから、一時テーブルを結合できますか? UDFがネストされていない場合、クエリは単に複雑すぎて効率的に実行できません。オプティマイザは、理想的な計画を見つけるのに1週間かかることがあります。テンポラリテーブル(テーブル変数ではありません)では、丁寧な改善が得られるでしょう。

私は自分自身は、いくつかの大きなクエリ(金融商品のプライシングの木を生成する)

事実はあなた15万行でこの技術を使用しましたが、私は数える複雑性の影に隠れています。

編集:彼らは唯一のマクロであるため

TVFSは、パラメータマスキングは必要ありません。文字通りそれをCTEまたは派生テーブルで置き換えることができます。

ここに私の答えを参照してください:Does query plan optimizer works well with joined/filtered table-valued functions そしてTony Rogerson on Views

+0

私はSPでのパラメータのマスキングを意味すると仮定します。最初に見たときに、インラインTVFでパラメータマスキングを行う方法を見つけることができなかったためです。はい、私はすべてのSPのためにそれを行います。 2008年にOPTIMIZE FOR UNKNOWNオプションを使用できるようにしたいと考えています。 –

+0

離散オブジェクトではないため、TVFをマスキングする必要はありません。これは、含まれているクエリに展開されます。更新された答え – gbn

0

ワン(:あなたは、私も一時テーブルとテーブル変数でプレーしてきたコメントアウトセクションから見ることができます結果として得られるテーブルは、テーブル変数のように、カラム統計を持たず、インデックスも持たないということです。

私は注意してTVFを使用する傾向があります。

+0

レベル6でも、関数から返されるテーブルは小さいです - 私は150,000行と思います。 –

+0

これらはすべてインラインテーブル値関数です。 –

+0

私は基本的にパラメータ化されたビューとして理解されていると理解しています。つまり、オプティマイザはインラインで書かれた場合と同じように、 –

0

擬似SQLではなく、実際のT-SQLを投稿できますか? テーブルのように@LVL_NUMが大きくなり、おそらくRECOMPILEは役に立ちません。しかし、疑似SQLに基づいて、疑似推測以外の何かを与えるのは本当に難しいです...

+0

実際のコードを投稿しました。 –

+0

テストケースが郵便で転記されたと思われ、コード自体からudf_MR_ALSRCが欠落しています。あなたはまた、参加者テーブルのテーブルサイズの球場を与えることができますか? –

+0

また、SCHEMABINDINGを追加しようとしていますが、なぜそれを削除しましたか? –

関連する問題