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

정산 등록 화면의 예상 보정액 한 줄이 0.4초, 결과 캐시를 붙이자는 안이 올라왔다

실전SELECT한빛유통664 / 700

상황 ​

정산 등록 화면 맨 위의 「이번 주 예상 보정액」은 정산 10만 건에 보정률 함수 FN_ADJ_RATE를 곱해 더한 한 줄이다. 정산팀 10명이 화면을 열 때마다 계산되어 하루 600번쯤 돌고, 한 번에 0.4초가 걸린다. 선배는 함수에 RESULT_CACHE 한 단어를 붙이자고 했고, 박팀장은 대안을 숫자로 견주어 하나를 고르고 무엇을 잃는지도 적어 달라고 했다. 보정률 규칙(등급 A 0.1%, B 0.2%, 그 밖 0.3%)은 정산팀 규정이고, 이 함수는 정산 등록(한 건)과 주간 보정 배치도 함께 쓴다.

테이블과 인덱스 ​

  • T_ORD_STLM 정산: 100,000행 · 640블록(실측 복사본은 549블록) · 고객 2,000명이 50건씩, 고객 순서가 아니라 섞여 있다
  • M_CUS 고객: 2,000행 · 30블록 · PK_M_CUS (CUS_ID) · CUS_GD A 20명 · B 180명 · C 1,800명 · 등급은 분기마다 다시 매긴다
  • 결과 캐시: 1,984칸(답 하나가 칸 하나) · result_cache_mode = MANUAL · result_cache_integrity = TRUSTED
  • 통계 최신

원본 SQL ​

sql
CREATE OR REPLACE FUNCTION FN_ADJ_RATE(p_cus_id VARCHAR2) RETURN NUMBER IS
  v_gd M_CUS.CUS_GD%TYPE;
BEGIN
  SELECT CUS_GD INTO v_gd FROM M_CUS WHERE CUS_ID = p_cus_id;
  RETURN CASE v_gd WHEN 'A' THEN 0.001 WHEN 'B' THEN 0.002 ELSE 0.003 END;   -- 정산팀 규정
END;
/

-- 이번 주 예상 보정액 (정산 등록 화면 맨 위)
SELECT SUM(ROUND(STLM_AMT * FN_ADJ_RATE(CUS_ID))) AS adj_sum
  FROM T_ORD_STLM;

실행계획 실측 · 교재 15b화(① ~ ④) · 개선안 수치는 학습용 예시 ​

xplan
[① 그대로: DISPLAY_CURSOR (ALLSTATS LAST) · 복사본]
-----------------------------------------------------------------------------------------
| Id  | Operation          | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |            |      1 |        |      1 |00:00:00.41 |     549 |
|   1 |  SORT AGGREGATE    |            |      1 |      1 |      1 |00:00:00.41 |     549 |
|   2 |   TABLE ACCESS FULL| T_ORD_STLM |      1 |   100K |   100K |00:00:00.01 |     549 |
-----------------------------------------------------------------------------------------

[네 판 비교: 판마다 두 번 (교재 15b화 실습/02 · 여덟 번 돌린 범위)]
 판                                 함수 본문    찾기     만들기   경과          논리 읽기   예상 보정액
 ① 그대로                            100,000        0         0   39 ~ 43 cs     300,527   73,753,436
 ② 스칼라 서브쿼리로 감싸기           57,664        0         0   23 ~ 26 cs     173,519   73,753,436
 ③ DETERMINISTIC 추가                 57,664        0         0   23 ~ 25 cs     173,519   73,753,436
 ④ RESULT_CACHE 추가 · 첫 판          14,467   85,533    14,467   17 ~ 18 cs      43,950   73,753,436
 ④ RESULT_CACHE 추가 · 두 번째 판     12,551   87,449    12,551   16 ~ 17 cs      38,180   73,753,436
   (④의 밀어내기: 첫 판 12,497 · 두 번째 판 12,551)

문제 ​

  1. ②와 ③이 57,664에서, ④가 두 번째 판에도 12,551에서 멈춘 이유를 각각 설명하시오.
  2. 보정률 규칙은 함수 하나에만 둔 채, 결과가 바뀌지 않으면서 함수 호출을 고객 수(2,000번) 이하로 줄이는 SQL을 쓰시오.
  3. 고른 안과 ② ~ ④, 그리고 규칙을 SQL의 CASE로 옮기는 안을 견주어 각각 무엇을 잃는지 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자