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

정산 명세 파일 내려받기가 첫 줄을 받기까지 2초를 기다리고, 세션마다 PGA가 60MB를 넘는다

기초PLSQL한빛유통680 / 700

상황 ​

정산팀의 파일 내려받기 도구는 SELECT … FROM TABLE(PKG_STLM_FILE.FN_LINES)로 은행 제출용 정산 명세 10만 줄을 받아 한 줄씩 파일에 쓴다. 줄의 모양(고정 길이, 자릿수, 검증 숫자)은 패키지의 PL/SQL 규칙이 만들고, 같은 패키지를 다른 제출 파일 세 개가 함께 쓴다. 내려받기를 누르면 2초 넘게 아무것도 오지 않다가 한꺼번에 들어온다. 월말에 네 명이 동시에 받던 날, DBA가 세션마다 PGA가 60MB를 넘었다고 알려 왔다.

테이블과 인덱스 ​

  • T_ORD_STLM 정산: 100,000행 · 640블록 · STLM_SEQ · ORD_SEQ · CUS_ID · STLM_DT · STLM_AMT
  • SQL 타입 T_LINE_OBJ (STLM_SEQ NUMBER, LINE VARCHAR2(200))와 T_LINE_TAB(TABLE OF T_LINE_OBJ)
  • FN_FMT_LINE: 패키지 안의 PL/SQL 함수(SQL 없음) · 정산 한 건을 200자 한 줄로 만든다
  • 파일의 줄 순서는 정해져 있지 않다(은행은 STLM_SEQ로 대조한다) · 내려받기 도구는 한 번에 500줄씩 가져온다

원본 SQL ​

sql
CREATE OR REPLACE PACKAGE BODY PKG_STLM_FILE IS
  FUNCTION FN_LINES RETURN T_LINE_TAB IS
    v_tab T_LINE_TAB := T_LINE_TAB();
  BEGIN
    FOR r IN (SELECT STLM_SEQ, ORD_SEQ, CUS_ID, STLM_DT, STLM_AMT
                FROM T_ORD_STLM) LOOP
      v_tab.EXTEND;
      v_tab(v_tab.COUNT) := T_LINE_OBJ(r.STLM_SEQ,
                              FN_FMT_LINE(r.STLM_SEQ, r.ORD_SEQ, r.CUS_ID, r.STLM_DT, r.STLM_AMT));
    END LOOP;
    RETURN v_tab;
  END;
  -- FN_FMT_LINE 생략
END;
/

-- 내려받기 도구
SELECT STLM_SEQ, LINE FROM TABLE(PKG_STLM_FILE.FN_LINES);

실행계획 학습용 예시 ​

xplan
[내려받기 도구의 문장: DISPLAY_CURSOR (ALLSTATS LAST)]
-------------------------------------------------------------------------------------------------------
| Id  | Operation                         | Name     | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                  |          |      1 |        |   100K |00:00:02.36 |       0 |
|   1 |  COLLECTION ITERATOR PICKLER FETCH| FN_LINES |      1 |   8168 |   100K |00:00:02.36 |       0 |
-------------------------------------------------------------------------------------------------------

[세션 통계: 내려받기 한 번]
  첫 페치까지                2.21 초
  전체 경과                  2.36 초
  session pga memory max     61.8 MB
  session logical reads      643   (함수 안 SQL이 T_ORD_STLM을 한 번 읽는다)
  FN_FMT_LINE 호출           100,000

문제 ​

  1. 첫 줄이 2초 넘게 오지 않고 세션 메모리가 60MB를 넘는 이유를 함수의 모양으로 설명하시오.
  2. 줄 규칙(FN_FMT_LINE)은 그대로 두고, 첫 줄이 바로 오고 메모리가 줄 수와 상관없이 작게 유지되도록 함수를 고치시오. 고친 뒤에도 줄지 않는 일은 무엇인지 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자