PL / SQL过程花费太长时间才能插入1,493,298行

时间:2019-07-02 16:44:10

标签: oracle performance plsql

我正在破坏'POST_DAILY_GL'过程,它正在调用另一个过程'IN_LEDGER_STAT_DAILY',该过程正在'LEDGER_STAT_DLY'表中插入/更新数据。 “ POST_DAILY_GL”过程每天都会在prod中运行,但是当我在测试环境中运行该过程时,要花费150万条记录是永远的。我已经在每1000条记录中添加了一次commit,这表明大约需要25个小时。发布150万条记录。 我可以要求建议在此过程中可以进行哪些改进。

***--'POST_DAILY_GL' procedure*** 
PROCEDURE POST_DAILY_GL(V_RUN_DATE NUMBER DEFAULT 0) AS

BEGIN

IF V_RUN_DATE = 0  THEN
    SELECT INSTR_AS_OF_DATE INTO V_DATE FROM AS_OF_DATE;
ELSE
    V_DATE := TO_DATE(LPAD(V_RUN_DATE, 8, '0'),'mmddyyyy');
END IF;

        i :=0;        

        V_DATE_PARAM := RETURN_DATE(V_DATE);



        V_SQL := q'[SELECT A.ACCOUNT_TYPE, B.FIN_ELEM, A.ORG_UNIT_ID, A.GL_ACCOUNT_ID, B.CMN_COA_ID, B.PROD1, B.PROD2, B.PROD3,
                 SUM(CURRENT_BAL) AS CB_SUM, SUM(AVG_BAL) AS AB_SUM, B.FLAG1 FROM DAILYGL A, AL_LOOKUP B
                 WHERE A.GL_ACCOUNT_ID = B.GL_ACCT AND A.AS_OF_DATE = :V_DATE_PARAM
                  GROUP BY A.ACCOUNT_TYPE, B.FIN_ELEM, A.ORG_UNIT_ID, A.GL_ACCOUNT_ID,B.CMN_COA_ID, B.PROD1, 
                 B.PROD2, B.PROD3, A.AS_OF_DATE, B.FLAG1]';


    OPEN seq FOR V_SQL using V_DATE_PARAM;

            LOOP
                V_SWITCH := 1;           
                FETCH seq INTO
                            V_ACCT_TYPE,   
                            V_FIN,
                            V_ORG_UNIT_ID,
                            V_GL_ACCOUNT_ID,
                            V_CMN_COA_ID,
                            V_PROD1, 
                            V_PROD2, 
                            V_PROD3,
                            V_END_BAL,  --cb
                            V_AVG_BAL,  --ab
                            V_FLAG;                                 
                EXIT WHEN seq%NOTFOUND;


                IF V_FLAG = 'Y' THEN
                    V_SWITCH :=  -1;
                ELSE
                    V_SWITCH := 1;
                END IF;

                IF V_ACCT_TYPE = 5 OR V_ACCT_TYPE = 10 OR V_ACCT_TYPE = 20 OR V_ACCT_TYPE = 35 THEN
                    V_SWITCH := V_SWITCH * -1;
                END IF;


                IF (V_END_BAL <> 0 OR V_AVG_BAL <>0) THEN  
                         IF V_ACCT_TYPE = 1 OR V_ACCT_TYPE = 5 OR V_ACCT_TYPE = 10 OR V_ACCT_TYPE = 90 THEN    

                                V_FIN1 := SUBSTR(V_FIN,1,2) || '100';

                                IN_LEDGER_STAT_DAILY(V_IDENTITY_CODE,V_CONSOLIDATION_CD,V_FIN1,V_ORG_UNIT_ID,V_GL_ACCOUNT_ID,V_CMN_COA_ID,
                                                    V_PROD1, V_PROD2, V_PROD3,V_DATE_PARAM,V_SWITCH * V_END_BAL);

                                IN_LEDGER_STAT_DAILY(V_IDENTITY_CODE,V_CONSOLIDATION_CD,V_FIN,V_ORG_UNIT_ID,V_GL_ACCOUNT_ID,V_CMN_COA_ID,
                                                    V_PROD1, V_PROD2, V_PROD3,V_DATE_PARAM,V_SWITCH * V_AVG_BAL);                      
                         ELSE
                                IN_LEDGER_STAT_DAILY(V_IDENTITY_CODE,V_CONSOLIDATION_CD,V_FIN,V_ORG_UNIT_ID,V_GL_ACCOUNT_ID,V_CMN_COA_ID,
                                                    V_PROD1, V_PROD2, V_PROD3,V_DATE_PARAM,V_SWITCH * V_END_BAL);               

                         END IF;
                END IF;


            i:=i + 1;
            if mod(i, 1000)=0 then
            insert into AL_STARTSTOP_SAC values('1000 recs committed at '||to_char(sysdate,'dd-mon-yyyy hh:mi:ss am'));
            commit;
            end if;

            END LOOP;

    CLOSE seq;

END POST_DAILY_GL; 

***--'IN_LEDGER_STAT_DAILY' procedure which is inserting/updating data***

PROCEDURE IN_LEDGER_STAT_DAILY 
    (
        V_IDENTITY_CODE      NUMBER,    
        V_CONSOLIDATION_CD   NUMBER,    
        V_FINANCIAL_ELEM_ID  NUMBER,    
        V_ORG_UNIT_ID        NUMBER,   
        V_GL_ACCOUNT_ID      NUMBER,    
        V_COMMON_COA_ID      NUMBER,   
        V_PRODUCT_1_ID       NUMBER,   
        V_PRODUCT_ID         NUMBER,   
        V_PRODUCT_3_ID       NUMBER,    
        V_DATE               DATE,        
        V_AMOUNT             NUMBER,    
        V_MEMO_GL_ACCOUNT_ID NUMBER DEFAULT 0,  
        V_POSTINGTYPE        CHAR DEFAULT 'N', 
        V_BALANCE_TYPE_CD    NUMBER DEFAULT 0 
)
IS

V_CNT NUMBER;
V_MONTH CHAR(2);
V_MO NUMBER;
V_YEAR_S NUMBER;




BEGIN              


   IF V_POSTINGTYPE = 'N' THEN

        IF NVL(V_AMOUNT,0) <> 0  THEN

                V_MO := (MONTH(V_DATE));
                V_MONTH := LPAD(V_MO,2,'0');
                V_YEAR_S := (YEAR(V_DATE));

                SELECT 
                COUNT(*) INTO V_CNT
                FROM LEDGER_STAT_DLY A
                WHERE
                IDENTITY_CODE         = NVL(V_IDENTITY_CODE,0)
                AND YEAR_S            = NVL(V_YEAR_S,0)
                AND MONTH_NO          = NVL(V_MONTH,0) 
                AND CONSOLIDATION_CD  = NVL(V_CONSOLIDATION_CD,0)
                AND FINANCIAL_ELEM_ID = NVL(V_FINANCIAL_ELEM_ID,0)
                AND ORG_UNIT_ID       = NVL(V_ORG_UNIT_ID,0)
                AND GL_ACCOUNT_ID     = NVL(V_GL_ACCOUNT_ID,0)
                AND COMMON_COA_ID     = NVL(V_COMMON_COA_ID,0)
                AND PRODUCT_1_ID      = NVL(V_PRODUCT_1_ID,0)
                AND PRODUCT_ID        = NVL(V_PRODUCT_ID,0)
                AND PRODUCT_3_ID      = NVL(V_PRODUCT_3_ID,0)
                AND COST_TYPE_ID      = NVL(V_MEMO_GL_ACCOUNT_ID,0)
                AND BALANCE_TYPE_CD   = NVL(V_BALANCE_TYPE_CD,0)    ;

                IF V_CNT = 0 THEN

                            INSERT INTO LEDGER_STAT_DLY VALUES(
                            NVL(V_IDENTITY_CODE,0),
                            NVL(V_YEAR_S,0)       ,
                            NVL(V_MONTH,0)        ,
                            'D',
                            NVL(V_CONSOLIDATION_CD,0),
                            NVL(V_FINANCIAL_ELEM_ID,0),
                            NVL(V_ORG_UNIT_ID,0)     ,
                            NVL(V_GL_ACCOUNT_ID,0)   ,
                            NVL(V_COMMON_COA_ID,0)   ,
                            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                            0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                            NVL(V_PRODUCT_1_ID,0)    ,
                            NVL(V_PRODUCT_ID,0)    ,
                            NVL(V_PRODUCT_3_ID,0)    ,
                            TRUNC(NVL(V_ORG_UNIT_ID,0) / 10000000),
                            'USD',                             
                            NULL,                              
                            NVL(V_BALANCE_TYPE_CD,0),
                            0,                                
                            NVL(V_MEMO_GL_ACCOUNT_ID,0),       
                            0                                  
                            );
              END IF;

            CASE DAY(V_DATE)
                WHEN 1 THEN
                UPDATE LEDGER_STAT_DLY A
                    SET DAY_01 =  NVL(DAY_01,0) + NVL(V_AMOUNT,0)
                    WHERE IDENTITY_CODE =  NVL(V_IDENTITY_CODE,0)
                            AND YEAR_S =  NVL(V_YEAR_S,0)
                            AND MONTH_NO = NVL(V_MONTH,0)
                            AND CONSOLIDATION_CD =  NVL(V_CONSOLIDATION_CD,0)
                            AND FINANCIAL_ELEM_ID =  NVL(V_FINANCIAL_ELEM_ID,0)
                            AND ORG_UNIT_ID   = NVL(V_ORG_UNIT_ID,0)
                            AND GL_ACCOUNT_ID = NVL(V_GL_ACCOUNT_ID,0)
                            AND COMMON_COA_ID = NVL(V_COMMON_COA_ID,0)
                            AND PRODUCT_1_ID  = NVL(V_PRODUCT_1_ID,0)
                            AND PRODUCT_ID    = NVL(V_PRODUCT_ID,0)
                            AND PRODUCT_3_ID  = NVL(V_PRODUCT_3_ID,0)
                            AND COST_TYPE_ID    = NVL(V_MEMO_GL_ACCOUNT_ID,0)
                            AND BALANCE_TYPE_CD = NVL(V_BALANCE_TYPE_CD,0);

            -- and same logic applies for all other days (2-31) of month

                ELSE

                    DBMS_OUTPUT.PUT_LINE('Please enter valid input for Day#: ');

            END CASE;

        END IF; 

    END IF;  --CLOSURE FOR POSTING TYPE IF STATEMENT



END IN_LEDGER_STAT_DAILY;

很抱歉,如果有人发现代码段太长。我将大部分代码放在这里,因此不会在不知不觉中遗漏某些东西。期待提出建议,并提前感谢您的帮助。

0 个答案:

没有答案