테마
본사 유통 DB의 spfile에는 2012년 이관 때 넣은 세 줄이 있다. optimizer_mode = FIRST_ROWS, optimizer_index_cost_adj = 20, optimizer_index_caching = 80. 넣은 사람도 이유도 남아 있지 않다. 박팀장은 다음 달 정기 점검 때 기본값으로 되돌리자고 했다. "단, 점장 화면이 하나라도 느려지면 안 돼요."
조민우가 복사본(같은 데이터, 같은 통계)에서 대표 SQL 셋을 지금 설정 세션과 기본값 세션으로 각각 쟀다.
CF10 판매: 500,000행 · 4,583블록 · CF10_PK (SLE_NO)(SLE_NO는 날짜로 시작해 판매 순서와 같다) · IX_CF10_SLE_DT (SLE_DT) · 매장 6곳(매장당 약 83,000건) · SLE_DT VARCHAR2(8)CF11 판매상품: 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO) 높이 3CF12 발주 734행 · 10블록 / CF13 발주상품 7,102행 · 57블록 · 각각 PK(ORD_NO, ORD_NO + ITM_NO)-- 박팀장 안 (다음 달 정기 점검 · 재기동)
ALTER SYSTEM RESET optimizer_mode SCOPE = SPFILE;
ALTER SYSTEM RESET optimizer_index_cost_adj SCOPE = SPFILE;
ALTER SYSTEM RESET optimizer_index_caching SCOPE = SPFILE;
-- S1 점장 화면 「최근 판매」 : 화면은 20행만 받고 커서를 닫는다 (하루 3,000번)
SELECT SLE_NO, SLE_DT, SLE_HMS
FROM CF10
WHERE SHP_NO = :shp
ORDER BY SLE_NO DESC;
-- S2 본부 「월 상품 판매」 (하루 40번)
SELECT b.ITM_NO, SUM(b.SLE_QTY) AS qty
FROM CF10 a, CF11 b
WHERE a.SLE_DT BETWEEN :d1 AND :d2
AND b.SLE_NO = a.SLE_NO
GROUP BY b.ITM_NO;
-- S3 「발주 상세」 (하루 500번)
SELECT d.ITM_NO, d.ORD_QTY
FROM CF12 h, CF13 d
WHERE h.ORD_NO = :ord
AND d.ORD_NO = h.ORD_NO;
[복사본 측정 — 두 설정]
지금 설정 (FIRST_ROWS · 20 · 80) 기본값 (ALL_ROWS · 100 · 0)
S1 INDEX FULL SCAN DESCENDING CF10_PK · 7블록 (20행에서 멈춘다) TABLE ACCESS FULL + SORT ORDER BY · 4,583블록 · 0.19초
S2 NESTED LOOPS (CF11_PK 20,953번) · 84,500블록 · 0.31초 HASH JOIN (CF11 FULL) · 8,457블록 · 0.12초
S3 NESTED LOOPS (PK 두 번) · 7블록 같은 계획 · 7블록
[S2 — 지금 설정 · 6월]
-------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 109 |00:00:00.31 | 84500 |
| 1 | HASH GROUP BY | | 1 | 109 | 109 |00:00:00.31 | 84500 |
|* 2 | FILTER | | 1 | | 45960 |00:00:00.29 | 84500 |
| 3 | NESTED LOOPS | | 1 | 5858 | 45960 |00:00:00.28 | 84500 |
| 4 | NESTED LOOPS | | 1 | 5858 | 45960 |00:00:00.17 | 63112 |
| 5 | TABLE ACCESS BY INDEX ROWID| CF10 | 1 | 2673 | 20953 |00:00:00.02 | 253 |
|* 6 | INDEX RANGE SCAN | IX_CF10_SLE_DT | 1 | 2673 | 20953 |00:00:00.01 | 60 |
|* 7 | INDEX RANGE SCAN | CF11_PK | 20953 | 2 | 45960 |00:00:00.11 | 62859 |
| 8 | TABLE ACCESS BY INDEX ROWID | CF11 | 45960 | 2 | 45960 |00:00:00.10 | 21388 |
-------------------------------------------------------------------------------------------------------
[S1 — 기본값 · 화면이 20행을 받고 닫았을 때]
-------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 20 |00:00:00.19 | 4583 |
| 1 | SORT ORDER BY | | 1 | 83333 | 20 |00:00:00.19 | 4583 |
|* 2 | TABLE ACCESS FULL | CF10 | 1 | 83333 | 83312 |00:00:00.07 | 4583 |
-------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(:D1<=:D2) (S2)
6 - access("A"."SLE_DT">=:D1 AND "A"."SLE_DT"<=:D2) (S2)
7 - access("B"."SLE_NO"="A"."SLE_NO") (S2)
2 - filter("SHP_NO"=:SHP) (S1)