테마
정산팀의 「최근 주문」 화면은 최신 주문 20건을 보여 주고, 같은 화면의 「엑셀 내려받기」 버튼은 최근 5만 건을 파일로 내린다. 개발팀은 두 기능이 같은 DAO 메서드를 쓰게 하고 건수만 인자로 넘겼다(화면 20, 엑셀 50,000). 화면은 하루 2만 번쯤 호출된다. 조민우가 말했다. "어제는 첫 페이지가 바로 떴는데 오늘은 한 박자 늦어요. 정산팀이 아침 8시 52분에 엑셀부터 내려받았다고 하더라고요." 밤사이 통계를 다시 모아서 이 문장의 커서는 오늘 아침에 새로 만들어졌다.
T_ORD_BIG: 1,000,000행 · 5,826블록 · 행은 ORD_DT 순서와 상관없이 흩어져 있다(인덱스로 1,000건을 읽으면 테이블 블록도 1,000개 가까이 읽는다)IX_ORD_BIG_DT_SEQ (ORD_DT, ORD_SEQ): 높이 3 · 리프 약 3,000블록ORD_ST에만 있다 · CURSOR_SHARING = EXACT · 바인드 피킹 켬// OrderDao.java : 화면과 엑셀이 같은 메서드를 쓴다 (화면 n = 20, 엑셀 n = 50000)
public List<OrderRow> recent(int n) throws SQLException {
String sql = "SELECT ORD_SEQ, CUS_ID, ORD_DT, ORD_AMT "
+ "FROM (SELECT ORD_SEQ, CUS_ID, ORD_DT, ORD_AMT FROM T_ORD_BIG "
+ "ORDER BY ORD_DT DESC, ORD_SEQ DESC) WHERE ROWNUM <= ?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setInt(1, n);
return readRows(ps.executeQuery());
}
}
[V$SQL — 오늘 09:30 · 커서는 08:52에 새로 만들어졌다]
CHILD PLAN_HASH EXECUTIONS BUFFER_GETS/EXEC FIRST_LOAD_TIME
0 2860115731 3,412 5,826 2024-06-17/08:52:07
[자식 0 · 화면(n = 20) 한 번 · FORMAT 'ALLSTATS LAST +PEEKED_BINDS']
Plan hash value: 2860115731
----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 20 |00:00:00.21 | 5826 | |
|* 1 | COUNT STOPKEY | | 1 | | 20 |00:00:00.21 | 5826 | |
| 2 | VIEW | | 1 | 50000 | 20 |00:00:00.21 | 5826 | |
|* 3 | SORT ORDER BY STOPKEY | | 1 | 1000K| 20 |00:00:00.21 | 5826 | 4096 (0)|
| 4 | TABLE ACCESS FULL | T_ORD_BIG | 1 | 1000K| 1000K|00:00:00.05 | 5826 | |
----------------------------------------------------------------------------------------------------------
Peeked Binds (identified by position):
--------------------------------------
1 - :1 (NUMBER): 50000
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=:1)
3 - filter(ROWNUM<=:1)
[어제 — 같은 문장 · 커서는 07:40에 화면(n = 20)이 처음 불렀다]
PLAN_HASH 1127394853 · INDEX FULL SCAN DESCENDING (IX_ORD_BIG_DT_SEQ) + TABLE ACCESS BY INDEX ROWID
화면 한 번 24블록 · 엑셀 한 번 50,158블록 (A-Rows 50,000)