테마
공유 풀 경보가 지난주 목요일부터 매일 오전에 울린다. 인프라팀은 이렇게 통보했다. "모양이 거의 같은 SQL이 끝도 없이 들어왔다 나간다. CURSOR_SHARING을 FORCE로 바꾸면 한 번에 정리된다. 오늘 밤 반영하겠다." 박팀장이 덧붙였다. "튜닝 쪽 의견을 오후 4시까지." 경보가 울린 시각에 공유 풀 맨 위를 차지한 문장은 정산 목록(Q4)이다. 리비전 파일에는 바인드로 적었는데, 개발팀은 포스트잇 값을 문자열로 이어 붙여 반영했다. 같은 공유 풀에는 2019년에 강도현이 탭마다 상수로 쓴 정산 상태 확인 문장 셋도 있다.
T_ORD_BIG: 1,000,000행 · 5,826블록 · ORD_ST(COMPLETE 90% · PENDING 8% · CANCEL 2%) · FREQUENCY 히스토그램IX_ORD_BIG_DT (ORD_DT) · IX_ORD_BIG_DT_AMT (ORD_DT, ORD_AMT) · IX_ORD_BIG_DT_SEQ (ORD_DT, ORD_SEQ)CURSOR_SHARING = EXACT · 바인드 피킹 켬 · statistics_level = TYPICAL-- 인프라팀 변경 요청 (오늘 밤 22:00)
ALTER SYSTEM SET CURSOR_SHARING = FORCE SCOPE = BOTH;
-- ① 정산 목록 '다음' — 개발팀 구현 (Java) : 포스트잇 값을 문자열로 이어 붙인다
-- String sql = "... WHERE ORD_DT <= DATE '" + postitDate + "' AND (ORD_DT < DATE '" + postitDate
-- + "' OR ORD_SEQ <= " + postitSeq + ") ORDER BY ORD_DT DESC, ORD_SEQ DESC) WHERE ROWNUM <= 11";
-- → 공유 풀에 들어오는 모양 (클릭마다 날짜 · 번호가 다르다)
SELECT ORD_SEQ, CUS_ID, ORD_DT, ORD_AMT
FROM (SELECT ORD_SEQ, CUS_ID, ORD_DT, ORD_AMT
FROM T_ORD_BIG
WHERE ORD_DT <= DATE '2024-12-30'
AND (ORD_DT < DATE '2024-12-30' OR ORD_SEQ <= 988784)
ORDER BY ORD_DT DESC, ORD_SEQ DESC)
WHERE ROWNUM <= 11;
-- ② 정산 상태 확인 — 강도현 2019 : 탭마다 문장 따로 (완료 · 미결 · 취소) · 상태값은 상수
SELECT ORD_SEQ, CUS_ID, ORD_DT, ORD_AMT
FROM (SELECT ORD_SEQ, CUS_ID, ORD_DT, ORD_AMT FROM T_ORD_BIG
WHERE ORD_ST = 'CANCEL' ORDER BY ORD_DT DESC, ORD_SEQ DESC)
WHERE ROWNUM <= 1000;
[① 3만 번 '다음' — 개발팀 구현 그대로 · 연습 DB 재현 · 세션 통계]
걸린 시간 36.19 초
parse count (total) 30,802
parse count (hard) 30,431
parse time cpu 3,466 (1/100 초)
CPU used by this session 3,617
session logical reads 522,931 (한 번 약 17 블록)
[V$SQLAREA — FORCE_MATCHING_SIGNATURE 로 묶은 맨 위 무리 (위 직후)]
PARENTS EXECS MB SQL_TEXT (앞부분)
308 308 9.4 SELECT ... WHERE ORD_DT <= DATE '2024-12-30' AND (ORD_DT < DATE '2024-12-30' OR ORD_SEQ <= 988784) ...
→ 부모 308 개가 지문 하나 · 3만 개가 '지나갔다' · 미리 올려 둔 이웃 Q1 rev03 은 V$SQL 에서 사라졌다
[인프라팀 제안을 내 세션에만 — ALTER SESSION SET CURSOR_SHARING = FORCE]
Q1 · Q2 · Q3 · Q4 계획 해시 그대로 · Buffers 91 · 5,868 · 839 · 15
3만 번 '다음' 1.45 초 · parse count (hard) 329 · 부모 1 · VERSION_COUNT 329 (지나간 날짜 329일)
V$SQL_SHARED_CURSOR 새 자식마다 HASH_MATCH_FAILED = Y
(같은 3만 번을 바인드로 · EXACT) 0.67 초 · parse count (hard) 1
[② 정산 상태 확인 — 탭마다 상수 (EXACT · 지금)]
탭 문장 계획 PLAN_HASH Buffers
완료 ORD_ST = 'COMPLETE' INDEX FULL SCAN DESCENDING (IX_ORD_BIG_DT_SEQ) 369784633 1,016
미결 ORD_ST = 'PENDING' TABLE ACCESS FULL + SORT ORDER BY STOPKEY 654798247 5,826
취소 ORD_ST = 'CANCEL' TABLE ACCESS FULL + SORT ORDER BY STOPKEY 654798247 5,826
(FORCE 아래의 상태 탭은 아직 재지 않았다)