테마
한빛유통 모바일 앱의 「주문 내역」 API는 고객의 최근 주문 20건과 주문마다 담긴 상품(이름, 수량, 단가)을 돌려준다. 지난달 API 서버를 클라우드로 옮긴 뒤 응답이 평균 0.04초에서 0.58초가 됐다. DB는 사내 IDC에 남았고 전용선으로 잇는다. APM은 요청 하나에 DB 호출이 61번이라고 보여 준다. DBA는 "61개 문장이 모두 한 번에 0.1ms 안쪽이라 DB는 잘못이 없다"라고 한다.
T_ORD: 100,000행 · 896블록 · PK_T_ORD (ORD_SEQ) · IX_T_ORD_CUS_DT (CUS_ID, ORD_DT)(SORT-006에서 만든 인덱스) · 고객 한 명에 주문 약 50건T_ORD_DET: 200,000행 · 896블록 · PK_T_ORD_DET (ORD_SEQ, ORD_DET_NO) · 주문당 1 ~ 3줄(평균 2줄)M_ITM: 100행 · 5블록 · PK_M_ITM (ITM_ID)// OrderHistoryApi.java : 주문 20건을 읽고, 주문마다 상품 줄을, 줄마다 상품명을 따로 읽는다 (JdbcTemplate)
List<Order> orders = jdbc.query(
"SELECT ORD_SEQ, ORD_DT, ORD_ST, ORD_AMT FROM ("
+ " SELECT ORD_SEQ, ORD_DT, ORD_ST, ORD_AMT FROM T_ORD WHERE CUS_ID = ? ORDER BY ORD_DT DESC"
+ ") WHERE ROWNUM <= 20", ORDER_MAPPER, cusId);
for (Order o : orders) {
o.lines = jdbc.query(
"SELECT ORD_DET_NO, ITM_ID, ORD_QTY, UNT_PRC FROM T_ORD_DET WHERE ORD_SEQ = ?", LINE_MAPPER, o.seq);
for (Line l : o.lines) {
l.itmNm = jdbc.queryForObject("SELECT ITM_NM FROM M_ITM WHERE ITM_ID = ?", String.class, l.itmId);
}
}
[요청 하나 · 고객 CUS_000731 · 세션 통계 증가분]
execute count 61
SQL*Net roundtrips to/from client 63
session logical reads 163
DB time 6.1 ms
SQL*Net message from client 63번 · 0.57 초 (평균 9.0 ms)
[V$SQL · 오늘 하루 (요청 31,200번)]
SQL EXECUTIONS 한 번 Buffers
SELECT ... FROM T_ORD WHERE CUS_ID = :1 ... ROWNUM <= 20 31,200 23
SELECT ORD_DET_NO, ... FROM T_ORD_DET WHERE ORD_SEQ = :1 624,000 3
SELECT ITM_NM FROM M_ITM WHERE ITM_ID = :1 1,248,000 2
[주문 20건 문장의 계획]
------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 20 |00:00:00.01 | 23 |
|* 1 | COUNT STOPKEY | | 1 | | 20 |00:00:00.01 | 23 |
| 2 | VIEW | | 1 | 50 | 20 |00:00:00.01 | 23 |
| 3 | TABLE ACCESS BY INDEX ROWID | T_ORD | 1 | 50 | 20 |00:00:00.01 | 23 |
|* 4 | INDEX RANGE SCAN DESCENDING | IX_T_ORD_CUS_DT | 1 | 50 | 20 |00:00:00.01 | 3 |
------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM<=20)
4 - access("CUS_ID"=:1)