Function 속도문제 질문좀 드릴꼐요 0 2 782

by 초보개발자민짱 [MySQL] [2016.11.28 11:34:38]


CREATE OR REPLACE FUNCTION HAKSA.SF_HR_GET_DRNAPBU_CHK(IN_YEAR IN VARCHAR2, IN_HAKGI IN VARCHAR2, IN_HAKBEON IN VARCHAR2, IN_GBCD IN VARCHAR2 )  

RETURN VARCHAR2 IS  
    V_NAPBU_GBCD VARCHAR2(100);
    V_NAPBU_YN     VARCHAR2(100);
    V_NAPBU_DEUNGROKGEUM_GYE NUMBER(10);
    V_DEUNGROKGEUM_NAPBU_DT      VARCHAR2(100);
    V_SUNGMIN VARCHAR2(100);  
BEGIN  
  
        SELECT
                          CASE WHEN ( NVL(A.CHAEKJEONG_DEUNGROKGEUM_GYE,'0') - NVL(A.GAMMYEON_GYE,'0') - NVL(A.NAPBU_DEUNGROKGEUM_GYE,'0') ) = '0' 
                                    THEN '등록' 
                                   WHEN NVL(A.CHAEKJEONG_DEUNGROKGEUM_GYE, '0') < ( NVL(A.GAMMYEON_GYE,'0') - NVL(A.NAPBU_DEUNGROKGEUM_GYE,'0')  - NVL(B.HWANBUL_GYE, '0') )
                                    THEN '환불' ELSE '미등록' END AS NAPBU_GBCD 
                        , CASE WHEN ( NVL(A.CHAEKJEONG_DEUNGROKGEUM_GYE,'0') - NVL(A.GAMMYEON_GYE,'0') - NVL(A.NAPBU_DEUNGROKGEUM_GYE,'0') ) = '0' 
                                    THEN 'Y' ELSE 'N' END AS NAPBU_YN
                        , A.NAPBU_DEUNGROKGEUM_GYE
                        , A.DEUNGROKGEUM_NAPBU_DT
                        
         INTO  V_NAPBU_GBCD
                 , V_NAPBU_YN
                 , V_NAPBU_DEUNGROKGEUM_GYE
                 , V_DEUNGROKGEUM_NAPBU_DT
                        
        FROM
        (
            SELECT
                               YEAR  
                             , HAKGI
                             , HAKBEON
                             , MAX(CHAEKJEONG_DEUNGROKGEUM_GYE) AS CHAEKJEONG_DEUNGROKGEUM_GYE
                             , MAX(GAMMYEON_GYE) AS GAMMYEON_GYE
                             , SUM(NAPBU_DEUNGROKGEUM_GYE) AS NAPBU_DEUNGROKGEUM_GYE
                             , MIN(DEUNGROKGEUM_NAPBU_DT) AS DEUNGROKGEUM_NAPBU_DT
                     FROM HR_NAPBU_MST_M 
                     WHERE YEAR = IN_YEAR
                     AND HAKGI = IN_HAKGI
                     AND HAKBEON = IN_HAKBEON             
                     GROUP BY YEAR, HAKGI, HAKBEON    
        ) A
        LEFT OUTER JOIN 
        (
        SELECT
                           YEAR AS YEAR
                         , HAKGI  AS HAKGI
                         , HAKBEON  AS HAKBEON
                         , SUM(HWANBUL_GYE) AS HWANBUL_GYE
                 FROM HR_HWANBUL_M  
               WHERE YEAR = IN_YEAR
                    AND HAKGI = IN_HAKGI
                    AND HAKBEON = IN_HAKBEON
               GROUP BY YEAR,HAKGI,HAKBEON     
        ) B
        ON A.HAKBEON = B.HAKBEON
      AND A.YEAR = B.YEAR
      AND A.HAKGI = B.HAKGI        
  ;  
  
         IF IN_GBCD = '1' THEN
        V_SUNGMIN := V_NAPBU_GBCD;
    ELSIF IN_GBCD = '2' THEN
        V_SUNGMIN := V_NAPBU_DEUNGROKGEUM_GYE;
    ELSIF IN_GBCD = '3' THEN
        V_SUNGMIN := V_NAPBU_YN;
    ELSIF IN_GBCD = '4' THEN
        V_SUNGMIN := V_DEUNGROKGEUM_NAPBU_DT;   
    END IF;  
    
    RETURN V_SUNGMIN;
END;
/

 

값 4개를 던져 1.2.3.4조건에 따라서 리턴하는 펑션입니다.

실질적으로 4400건의 데이터를 이 펑션을 써서 조회하면 14초나 걸려버리네요 . 혹시 쿼리가 잘못됐는지 개선방법이 좀  조언받고 싶습니다.

 

by 마농 [2016.11.28 13:53:12]

1. 인덱스가 적절한지 확인 필요합니다.
  - 사용되는 두개 테이블에 (연도,학기,학번) 인덱스가 필요합니다.
2. 쓸데없이 사용된 코드를 최대한 줄여야 합니다.
  - NVL 의 경우 문자 '0' 을 넣음으로 인해 쓸데없이 형변환을 한번 더 하게 됩니다.
  - 이 부분만 10군데나 되네요.
  - '0' 을 0 으로 바꿔 주시구요.
  - a 의 NVL 은 서브쿼리 안으로 넣고 b 만 NVL 처리하면 될 듯 하구요.
3. 애매한 계산 규칙이 적용되었네요?
  - 등록과 환불의 경계가 모호하네요.
  - 환불의 경우 계산식도 적절하지 않아 보입니다.
 


by 초보개발자민짱 [2016.11.28 15:42:47]

참고하여 새로 짯습니다 ㅠㅠ

고맙습니다~

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입