테마
본사 레거시 유통의 「영수증 조회 · 반품」 화면(2011년, Java)은 매장 6곳에서 영수증 번호로 판매 한 건을 연다. 오전에만 3만 번쯤 호출된다.
DBA는 이렇게 말했다. "오전마다 공유 풀 경보와 latch: shared pool 대기가 뜹니다. CURSOR_SHARING을 FORCE로 바꾸면 한 번에 정리된다니 오늘 밤 반영하겠습니다." 같은 DB에는 다른 화면과 배치도 붙어 있다.
CF10 판매: 500,000행 · 4,583블록 · CF10_PK (SLE_NO) · SLE_NO VARCHAR2(15) '20230601-0123'(영수증 번호)CF11 판매상품: 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO) · 영수증 한 장에 상품 1~4개CF01 상품: 109행 · 5블록 · CF01_PK (ITM_NO)// ReceiptDao.java (2011) — 영수증 번호를 SQL 문자열에 이어 붙인다
String sql = "SELECT h.SLE_NO, h.SLE_DT, h.SLE_HMS, d.ITM_NO, i.ITM_NM, d.SLE_QTY, d.SLE_UPRC "
+ "FROM CF10 h, CF11 d, CF01 i "
+ "WHERE h.SLE_NO = '" + sleNo + "' "
+ "AND d.SLE_NO = h.SLE_NO AND i.ITM_NO = d.ITM_NO";
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql);
[오전 3만 번 — 연습 DB 에서 화면 그대로 재현 · 한 세션 (세션 통계 증가분)]
경과 시간 27.8 초
parse count (total) 30,214
parse count (hard) 30,012
parse time cpu 2,472 cs
CPU used by this session 2,630 cs
session logical reads 391,830 (한 번에 약 13 — 실행 11 + 하드 파싱의 딕셔너리 조회)
[V$SQL 에 보이는 것]
SELECT h.SLE_NO, h.SLE_DT, … WHERE h.SLE_NO = '20231105-0412' AND d.SLE_NO = h.SLE_NO AND i.ITM_NO = d.ITM_NO
SELECT h.SLE_NO, h.SLE_DT, … WHERE h.SLE_NO = '20231105-0413' AND d.SLE_NO = h.SLE_NO AND i.ITM_NO = d.ITM_NO
…
[3만 번 직후 V$SQLAREA 를 FORCE_MATCHING_SIGNATURE 로 묶어 센 것]
FMS PARENTS EXECS MB SAMPLE
11893327705119548241 386 386 7.9 SELECT h.SLE_NO, h.SLE_DT, h.SLE_HMS, d.ITM_NO, i.ITM_NM, d.SLE_Q…
[한 번 실행의 계획]
----------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 |00:00:00.01 | 11 |
| 1 | NESTED LOOPS | | 1 | 2 | 2 |00:00:00.01 | 11 |
| 2 | NESTED LOOPS | | 1 | 2 | 2 |00:00:00.01 | 9 |
| 3 | NESTED LOOPS | | 1 | 2 | 2 |00:00:00.01 | 8 |
| 4 | TABLE ACCESS BY INDEX ROWID | CF10 | 1 | 1 | 1 |00:00:00.01 | 4 |
|* 5 | INDEX UNIQUE SCAN | CF10_PK | 1 | 1 | 1 |00:00:00.01 | 3 |
| 6 | TABLE ACCESS BY INDEX ROWID BATCHED| CF11 | 1 | 2 | 2 |00:00:00.01 | 4 |
|* 7 | INDEX RANGE SCAN | CF11_PK | 1 | 2 | 2 |00:00:00.01 | 3 |
|* 8 | INDEX UNIQUE SCAN | CF01_PK | 2 | 1 | 2 |00:00:00.01 | 1 |
| 9 | TABLE ACCESS BY INDEX ROWID | CF01 | 2 | 1 | 2 |00:00:00.01 | 2 |
----------------------------------------------------------------------------------------------------
5 - access("H"."SLE_NO"='20231105-0412')
7 - access("D"."SLE_NO"='20231105-0412')
8 - access("I"."ITM_NO"="D"."ITM_NO")
V$SQL에 남은 문장은 386개뿐인데 '3만 개'라고 말할 수 있는 근거도 쓰시오.CURSOR_SHARING = FORCE 안을 평가하시오.