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

월 마감의 매장별 주문 집계만 다른 집계보다 열 배 오래 걸린다

기초INSERT버거657 / 700

상황 ​

버거 본사의 월 마감 배치는 상품별, 일자별, 매장별 주문 집계를 차례로 적재한다. 다른 집계는 0.05 ~ 0.07초인데 「매장별 주문 수」만 0.6초가 넘는다. 셋 다 같은 한 달 치 주문을 ORD_X01 범위로 읽는다. 매장별 집계는 매장명으로 묶어 넣는다. 매장명은 POS 공통 함수 FN_SHOP_NM이 붙인다.

테이블과 인덱스 ​

  • ORD 주문: 1,000,000행 · 22,422블록 · ORD_DT VARCHAR2(8) · 2013년 12월 41,712건 · ORD_X01 (ORD_DT, ORD_HMS) 리프 3,774블록 · CF 22,223
  • SHOP 매장: 200행 · 5블록 · PK(SHOP_NO) · SH0070과 SH0089는 둘 다 '여의도점'이다
  • T_SHOP_MON_ORD 월 매장 집계(이 배치가 채운다): ORD_YM · SHOP_NM · ORD_CNT · 인덱스 없음 · 지난달 적재 결과는 199행
  • 통계 최신

원본 SQL ​

sql
CREATE OR REPLACE FUNCTION FN_SHOP_NM(p_shop_no VARCHAR2) RETURN VARCHAR2 IS
  v_nm SHOP.SHOP_NM%TYPE;
BEGIN
  SELECT SHOP_NM INTO v_nm FROM SHOP WHERE SHOP_NO = p_shop_no;
  RETURN v_nm;
END;
/

INSERT INTO T_SHOP_MON_ORD (ORD_YM, SHOP_NM, ORD_CNT)
SELECT '201312', FN_SHOP_NM(SHOP_NO), COUNT(*)
  FROM ORD
 WHERE ORD_DT BETWEEN '20131201' AND '20131231'
 GROUP BY FN_SHOP_NM(SHOP_NO);

실행계획 학습용 예시 ​

xplan
[DISPLAY_CURSOR (ALLSTATS LAST)]
------------------------------------------------------------------------------------------------------------------
| Id  | Operation                             | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT                      |                |      1 |        |      0 |00:00:00.63 |    1093 |
|   1 |  LOAD TABLE CONVENTIONAL              | T_SHOP_MON_ORD |      1 |        |      0 |00:00:00.63 |    1093 |
|   2 |   HASH GROUP BY                       |                |      1 |  41667 |    199 |00:00:00.63 |    1086 |
|   3 |    TABLE ACCESS BY INDEX ROWID BATCHED| ORD            |      1 |  41667 |  41712 |00:00:00.02 |    1086 |
|*  4 |     INDEX RANGE SCAN                  | ORD_X01        |      1 |  41667 |  41712 |00:00:00.01 |     159 |
------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   4 - access("ORD_DT">='20131201' AND "ORD_DT"<='20131231')

[세션 통계: 이 INSERT 한 번]
  경과 시간                 0.63 초
  recursive calls           41,734
  session logical reads     84,530

[V$SQL: 함수 안의 문장 (dep=1)]
  SELECT SHOP_NM FROM SHOP WHERE SHOP_NO = :B1    EXECUTIONS 41,712 · BUFFER_GETS 83,424

문제 ​

  1. 같은 범위를 읽는 다른 집계보다 열 배 느린 이유를 함수가 호출된 횟수로 설명하시오.
  2. 함수가 매장 수만큼만 호출되도록 SQL을 고치시오. 고친 SQL의 결과가 원래 SQL과 같은지 확인하고, 다르다면 어떻게 할지 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자