테마
고객센터의 「반품 접수」 화면은 주문번호를 넣으면 주문 상세 1 ~ 3줄과 줄마다 주문 시각의 판매가(최저가 연동 가격)를 보여 주고, 판매가와 실제 결제 단가의 차이로 환불액을 계산한다. 상담원이 하루 2천 번쯤 연다. 가격 이력이 날마다 쌓이면서 이 화면이 조금씩 무거워져, 요즘은 주문 한 건에 1,200블록 넘게 읽는다. 아래는 2024-12-08 14:22에 들어온 주문(상세 3줄)으로 잰 실행계획이다.
T_ORD: 100,000행 · 896블록 · PK_T_ORD (ORD_SEQ) · ORD_DT는 시분초 있음 / T_ORD_DET: 200,000행 · 896블록 · PK_T_ORD_DET (ORD_SEQ, ORD_DET_NO) · 주문당 1 ~ 3줄T_ITM_PRC_LOG 상품 판매가 이력 (이 문제에서 쓰는 파생 테이블, 선분이력): ITM_ID · ST_DTM · ED_DTM (다음 구간의 시작 시각, 이 시각 미만까지) · SLE_PRC · 최저가 연동 배치가 2023-01-01부터 매일 04시에 상품마다 새 구간을 연다 · 73,100행 · 410블록 · 상품마다 약 731구간IX_ITM_PRC_LOG (ITM_ID, ST_DTM): BLEVEL 1 · 리프 약 230블록(상품 하나에 약 2.3블록) · 날마다 100행씩 쌓여서 상품 하나의 구간은 테이블 거의 전체에 흩어져 있다SELECT d.ORD_DET_NO, d.ITM_ID, d.ORD_QTY, d.UNT_PRC, h.SLE_PRC AS LIST_PRC
FROM T_ORD o, T_ORD_DET d, T_ITM_PRC_LOG h
WHERE o.ORD_SEQ = :v_ord
AND d.ORD_SEQ = o.ORD_SEQ
AND h.ITM_ID = d.ITM_ID
AND h.ST_DTM <= o.ORD_DT
AND h.ED_DTM > o.ORD_DT
ORDER BY d.ORD_DET_NO
----------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 3 |00:00:00.03 | 1247 |
| 1 | SORT ORDER BY | | 1 | 2 | 3 |00:00:00.03 | 1247 |
| 2 | NESTED LOOPS | | 1 | 2 | 3 |00:00:00.03 | 1247 |
| 3 | NESTED LOOPS | | 1 | 730 | 2128 |00:00:00.01 | 17 |
| 4 | NESTED LOOPS | | 1 | 2 | 3 |00:00:00.01 | 7 |
| 5 | TABLE ACCESS BY INDEX ROWID | T_ORD | 1 | 1 | 1 |00:00:00.01 | 3 |
|* 6 | INDEX UNIQUE SCAN | PK_T_ORD | 1 | 1 | 1 |00:00:00.01 | 2 |
| 7 | TABLE ACCESS BY INDEX ROWID BATCHED| T_ORD_DET | 1 | 2 | 3 |00:00:00.01 | 4 |
|* 8 | INDEX RANGE SCAN | PK_T_ORD_DET | 1 | 2 | 3 |00:00:00.01 | 2 |
|* 9 | INDEX RANGE SCAN | IX_ITM_PRC_LOG | 3 | 365 | 2128 |00:00:00.01 | 10 |
|* 10 | TABLE ACCESS BY INDEX ROWID | T_ITM_PRC_LOG | 2128 | 1 | 3 |00:00:00.02 | 1230 |
----------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
6 - access("O"."ORD_SEQ"=:V_ORD)
8 - access("D"."ORD_SEQ"=:V_ORD)
9 - access("H"."ITM_ID"="D"."ITM_ID" AND "H"."ST_DTM"<="O"."ORD_DT")
10 - filter("H"."ED_DTM">"O"."ORD_DT")
(ITM_ID, ED_DTM, ST_DTM)으로 하나 더 만드는 안과 견주어, 어느 쪽을 고를지 근거와 함께 쓰시오.