Skip to content
튜닝 연습PL/SQL과 사용자 정의 함수
PLSQL-037

정산 분개 생성이 11초인데, 분개 규칙은 낮의 정산 등록과 같은 패키지라 SQL로 옮기기 어렵다

실전PLSQL한빛유통687 / 700

상황 ​

야간 체인의 「정산 분개 생성」 단계는 정산 10만 건마다 분개 줄(매출, 수수료, 부가세, 포인트 사용)을 3 ~ 4줄씩 만들어 T_STLM_JNL에 넣는다. 지금은 11.4초가 걸리고, 오과장은 이 단계에 3초를 배정하고 싶어 한다. 분개 규칙은 패키지 프로시저 PKG_JNL_RULE.MAKE_LINES에 있다(등급과 결제 수단에 따른 수수료율, 부가세 끝수 처리, 포인트 안분이 40줄쯤 된다). 낮에는 정산 등록 화면이 같은 프로시저로 한 건씩 분개를 만든다. 박팀장은 대안을 숫자로 견주어 하나를 고르고, 무엇을 잃는지도 적어 달라고 했다.

테이블과 인덱스 ​

  • T_ORD_STLM 정산: 100,000행 · 640블록 · M_CUS 고객: 2,000행 · 30블록 · CUS_GD A 1% · B 9% · C 90%
  • T_STLM_JNL 분개(이 배치가 채운다): STLM_SEQ · LINE_NO · ACCT_CD · DR_CR · JNL_AMT · JNL_DT · 정산 한 건에 3줄, 포인트를 쓴 22%는 4줄 · 이번 판 322,000줄
  • T_STLM_JNL은 배치를 시작할 때 비우고(TRUNCATE) 인덱스는 적재 뒤에 만든다 · 다른 세션은 체인이 끝난 뒤에 읽는다
  • PKG_JNL_RULE.T_LINES: 분개 줄 레코드의 PL/SQL 컬렉션 · DB는 NOARCHIVELOG · CPU 8코어 중 이 시간대에 4코어가 비어 있다

원본 SQL ​

sql
PROCEDURE P_MAKE_JNL IS
  v_lines PKG_JNL_RULE.T_LINES;
BEGIN
  EXECUTE IMMEDIATE 'TRUNCATE TABLE T_STLM_JNL';
  FOR r IN (SELECT s.STLM_SEQ, s.STLM_DT, s.STLM_AMT, c.CUS_GD
              FROM T_ORD_STLM s, M_CUS c
             WHERE c.CUS_ID = s.CUS_ID) LOOP
    PKG_JNL_RULE.MAKE_LINES(r.STLM_SEQ, r.CUS_GD, r.STLM_AMT, v_lines);   -- 정산 한 건 → 분개 3 ~ 4줄
    FOR i IN 1 .. v_lines.COUNT LOOP
      INSERT INTO T_STLM_JNL (STLM_SEQ, LINE_NO, ACCT_CD, DR_CR, JNL_AMT, JNL_DT)
      VALUES (r.STLM_SEQ, i, v_lines(i).ACCT_CD, v_lines(i).DR_CR, v_lines(i).AMT, r.STLM_DT);
    END LOOP;
  END LOOP;
  COMMIT;
END;

실행계획 학습용 예시 ​

xplan
[세션 통계: P_MAKE_JNL 한 번 (정산 100,000건 → 분개 322,000줄)]
  경과 시간                    11.4 초 (CPU 9.6 초)
  recursive calls              323,140
  execute count                322,012
  session logical reads        361,870
  redo size                    78.4 MB
  PL/SQL 규칙 (DBMS_HPROF)     MAKE_LINES 100,000번 · 0.62 초

[TKPROF: 재귀 문장 둘]
  SELECT S.STLM_SEQ, S.STLM_DT, S.STLM_AMT, C.CUS_GD FROM T_ORD_STLM S, M_CUS C WHERE C.CUS_ID = S.CUS_ID
     Execute 1 · Fetch 1,001 · rows 100,000 · query 672
  INSERT INTO T_STLM_JNL (STLM_SEQ, LINE_NO, ACCT_CD, DR_CR, JNL_AMT, JNL_DT) VALUES (:B6, :B5, :B4, :B3, :B2, :B1)
     Execute 322,000 · rows 322,000 · cpu 7.9 · elapsed 8.6 · query 3,140 · current 355,600

문제 ​

  1. 11.4초가 어디서 나오는지 세션 통계와 TKPROF로 설명하시오.
  2. 분개 규칙을 PKG_JNL_RULE 하나에 둔 채로, 파이프라인 테이블 함수와 INSERT … SELECT 한 문장으로 다시 쓰시오.
  3. ① BULK COLLECT와 FORALL, ② 2번의 파이프라인 함수, ③ 규칙을 SQL(CASE와 규칙표)로 옮긴 INSERT … SELECT를 견주어 하나를 고르고, 고른 안의 대가를 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자