테마
지난달 정산 상태 탭이 날마다 다른 탭에서 느렸던 일(PARSE-002)에 이어, 오늘 아침에는 「등급별 매출」 화면이 C 등급에서 3만 블록을 읽었다. 인프라팀이 메일을 보냈다. "바인드 값 때문에 계획이 흔들리는 일을 한 번에 없애겠습니다. 피킹을 끄고, 히스토그램을 지우고, 계획 베이스라인을 자동으로 잡아 두면 계획이 바뀔 일이 없습니다. 금요일 밤 반영 예정입니다." 박팀장이 덧붙였다. "세 가지를 따로 평가해 주세요. 반대한다면 대신 무엇을 할지도요."
T_ORD_BIG: 1,000,000행 · 5,826블록 · ORD_ST COMPLETE 90% · PENDING 8% · CANCEL 2% · FREQUENCY 히스토그램 · 6월 한 달 27,390건M_CUS: 2,000행 · 30블록 · CUS_GD A 20명 · B 180명 · C 1,800명 · FREQUENCY 히스토그램IX_ORD_BIG_DT · IX_ORD_BIG_DT_AMT (ORD_DT, ORD_AMT) · IX_ORD_BIG_DT_SEQ (ORD_DT, ORD_SEQ) · IX_ORD_BIG_CUS_DT (CUS_ID, ORD_DT) · PK_M_CUSCURSOR_SHARING = EXACT · 바인드 피킹 켬 · SQL Plan Baseline 없음 · statistics_level = TYPICAL-- 인프라팀 변경 요청 (금요일 22:00)
ALTER SYSTEM SET "_optim_peek_user_binds" = FALSE SCOPE = BOTH; -- ① 피킹 끄기
EXEC DBMS_STATS.SET_GLOBAL_PREFS('METHOD_OPT', 'FOR ALL COLUMNS SIZE 1'); -- ② 히스토그램 지우기 (그날 밤 다시 수집)
ALTER SYSTEM SET OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES = TRUE SCOPE = BOTH; -- ③ 계획 자동 수집 · 고정
-- 영향을 받는 문장 셋
-- [S1] 등급별 매출 화면 (바인드 : 등급과 조회월)
SELECT c.CUS_GD, COUNT(*) AS ORD_CNT, SUM(o.ORD_AMT) AS AMT
FROM M_CUS c, T_ORD_BIG o
WHERE c.CUS_GD = :gd
AND o.CUS_ID = c.CUS_ID
AND o.ORD_DT >= TO_DATE(:p_ym || '01', 'YYYYMMDD')
AND o.ORD_DT < ADD_MONTHS(TO_DATE(:p_ym || '01', 'YYYYMMDD'), 1)
GROUP BY c.CUS_GD;
-- [S2] 정산 상태 확인 · 취소 탭 (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;
-- [S3] 월 매출 Q1 (바인드 : 조회월 · 커버링 인덱스)
SELECT COUNT(*), SUM(ORD_AMT)
FROM T_ORD_BIG
WHERE ORD_DT >= TO_DATE(:p_ym || '01', 'YYYYMMDD')
AND ORD_DT < ADD_MONTHS(TO_DATE(:p_ym || '01', 'YYYYMMDD'), 1);
[S1 · 6월 · 지금 (피킹 켬 · 히스토그램 있음) · 등급마다 한 번의 Buffers]
A 등급 B 등급 C 등급
A로 태어난 커서 (NL) 372 3,035 30,081 ← NESTED LOOPS + IX_ORD_BIG_CUS_DT
C로 태어난 커서 (HASH) 5,858 5,858 5,858 ← T_ORD_BIG FULL + HASH JOIN
등급마다 맞는 계획 372 3,035 5,858
(A로 태어난 날은 A 372 → C 30,081 순서로 칸이 섞여 ACS가 한 번 뒤에 C를 HASH로 나눈다 · C로 태어난 날은 셋 다 1번 칸이라 그대로)
[S2 · 탭 셋 (상수)] 완료 1,016 · 미결 5,826 · 취소 5,826 (FREQUENCY 덕에 탭마다 맞는 계획)
[S3 · Q1] 어느 달이든 91 (커버링 인덱스 범위 스캔)
[① 피킹 끄기를 내 세션에만 (ALTER SESSION SET "_optim_peek_user_binds" = FALSE)]
S1 : 등급 값을 모른다 → CUS_GD E-Rows 667(1/3) → HASH 고정 · A 5,858 · B 5,858 · C 5,858
S2 : 상수라 그대로 (1,016 · 5,826 · 5,826)
S3 : 91 그대로
(교재 11화) 상태 탭을 바인드로 쓴 문장 · 셋 다 인덱스 계획 · 취소 50,347 / OR가 든 바인드 페이징(rev02 모양) · 2페이지 1,005,991
[② 복사본 스키마에서 히스토그램을 지우고 다시 모은 뒤]
S1 : CUS_GD E-Rows 667 → HASH 고정 · A 5,858
S2 : 'CANCEL' E-Rows 333,333 → 인덱스 계획(INDEX FULL SCAN DESCENDING) · 취소 50,347 · 미결 13,510 · 완료 1,016
S3 : 91 그대로
[③ 복사본에서 자동 수집을 켜고 하루 돌린 뒤 · DBA_SQL_PLAN_BASELINES]
S1 : ACCEPTED 1개(그날 처음 수집된 NESTED LOOPS) · 그 뒤 HASH JOIN 계획은 ACCEPTED = NO로만 쌓인다 → C 30,081이 계속
S2 : 탭마다 문장이 달라 베이스라인 셋 · 계획 그대로
베이스라인 하루 1,940개 생성 · SYSAUX 사용 증가