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

월요일 아침에 등록한 정산이 전부 지난 금요일 날짜다

중급PLSQL한빛유통652 / 700

상황 ​

09:11에 조민우가 알려 왔다. "오늘 아침에 등록한 정산이 전부 정산일 6/14(금)로 찍혀 있어요. 금요일 저녁 6시 넘어서 등록한 것도 6/14고요." 금요일 17:30에 정산 등록 화면의 응답 시간을 줄이려고, 화면이 호출하는 정산일 함수에 RESULT_CACHE 한 단어를 붙였다. 반영 전 연습 DB 대조(건수, 합계, MINUS)는 금요일 오후에 돌렸고 결과가 같았다.

테이블과 인덱스 ​

  • T_ORD_STLM 정산: 100,000행 · 640블록 · STLM_DT 정산일(전부 과거 날짜)
  • 정산일 규칙(2019 강도현): 18시 마감. 18시 전 등록은 그날, 18시 이후 등록은 다음 날 정산
  • 결과 캐시: 인스턴스에 하나뿐이고 모든 세션이 함께 쓴다 · result_cache_mode = MANUAL · result_cache_integrity = TRUSTED
  • 결과 캐시의 무효화: 결과가 기대는 객체(의존 객체)가 바뀌어 커밋되면 지운다

원본 SQL ​

sql
-- 정산일 함수 — 2019 강도현 (18시 마감 · DETERMINISTIC) + 6/14 17:30 'RESULT_CACHE' 한 단어
CREATE OR REPLACE FUNCTION FN_STLM_DT RETURN DATE DETERMINISTIC RESULT_CACHE IS
BEGIN
  RETURN TRUNC(SYSDATE + 6/24);      -- 18:00 + 6시간 = 다음 날 0시 → 18시 이후 등록은 다음 날 정산
END;
/

-- 정산 등록 화면이 부르는 곳
INSERT INTO T_ORD_STLM (STLM_SEQ, ORD_SEQ, CUS_ID, STLM_DT, STLM_AMT)
VALUES (:seq, :ord_seq, :cus_id, FN_STLM_DT, :amt);

SELECT STLM_SEQ, ORD_SEQ, CUS_ID, STLM_DT, STLM_AMT     -- 목록 : 정산일까지 온 정산
  FROM T_ORD_STLM
 WHERE STLM_DT <= FN_STLM_DT;

실행계획 교재 15b화 실측 · Buffers는 원본 규모 ​

xplan
[V$RESULT_CACHE_OBJECTS — 6/17 (월) 09:30]
 TYPE        STATUS     NAME                                           CREATION_TIMESTAMP
 Dependency  Published  SQLP.FN_STLM_DT                                06/14 17:31:02
 Result      Published  "SQLP"."FN_STLM_DT"::8."FN_STLM_DT"#… #1       06/14 17:31:02

[V$RESULT_CACHE_DEPENDENCY — 정산일 결과가 기대는 객체]
 SQLP.FN_STLM_DT   (함수 자신 하나 — 그 사이 정산 등록이 계속 커밋됐지만 Published 그대로)

[등록된 정산일]
 등록 시각            찍힌 STLM_DT    규칙대로라면
 06/14 (금) 17:45     2024-06-14      2024-06-14
 06/14 (금) 18:20     2024-06-14      2024-06-15
 06/17 (월) 08:55     2024-06-14      2024-06-17

[목록 문장 — 정산 10만 행 · 세 판 모두 같은 계획 (TABLE ACCESS FULL · 계획 해시도 같다)]
 판                                   함수 본문 실행   결과 캐시 찾기   Buffers
 그냥 함수 (DETERMINISTIC 없이)            100,000             0           640
 2019 원본 (DETERMINISTIC)                       1             0           640
 6/14 판 (+ RESULT_CACHE)                        0             1           640

문제 ​

  1. 정산일이 6/14에 멈춘 이유를 결과 캐시가 '같은 질문'을 판단하는 방법으로 설명하시오. 정산이 계속 등록됐는데도 캐시가 지워지지 않은 이유도 쓰시오.
  2. 정산일을 경계 시각으로 시험할 수 있게 함수를 고치고, 목록 문장이 행마다 함수를 호출하지 않게 하시오. 그 한 단어로 무엇을 얻었는지도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자