테마
고객센터의 「고객 주문 이력」은 고객 한 명의 한 달 치 주문을 보여 준다. 상담원 서른 명이 하루 6천 번쯤 연다. 조민우는 사내 위키에서 "BETWEEN을 IN 목록으로 바꾸면 뒤 컬럼도 access가 된다"는 글을 읽고, 한 달 범위를 날짜 30개짜리 IN 목록으로 바꿨다. 실행계획에서 filter는 사라졌지만 Buffers는 128 → 104로 거의 그대로다. 아래는 고객 CUS_000123의 2024년 6월이다.
T_ORD_BIG: 1,000,000행 · 5,826블록 · ORD_DT 하루 913건(전부 자정) · 2024년 6월 27,390건 · CUS_ID 2,000명(고객당 500건)IX_ORD_BIG_DT_CUS (ORD_DT, CUS_ID): 「일 정산 대사」(ORD_DT = :d, 고객순)용 · BLEVEL 2 · 리프 약 4,100블록(리프 한 블록에 약 245항목) · CLUSTERING_FACTOR 약 1,000,000 · 통계 최신-- 고치기 전
SELECT ORD_SEQ, ORD_DT, ORD_ST, ORD_AMT
FROM T_ORD_BIG
WHERE CUS_ID = :v_cus
AND ORD_DT >= TO_DATE(:v_from, 'YYYYMMDD')
AND ORD_DT < TO_DATE(:v_to, 'YYYYMMDD') + 1;
-- 조민우가 고친 판 (화면이 그달의 날짜 수만큼 IN 목록을 만든다)
SELECT ORD_SEQ, ORD_DT, ORD_ST, ORD_AMT
FROM T_ORD_BIG
WHERE CUS_ID = :v_cus
AND ORD_DT IN (TO_DATE(:d01, 'YYYYMMDD'), TO_DATE(:d02, 'YYYYMMDD'), TO_DATE(:d03, 'YYYYMMDD'),
/* … :d04 ~ :d29 … */
TO_DATE(:d30, 'YYYYMMDD'));
[고치기 전 — 범위]
--------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
--------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 14 |00:00:00.01 | 128 |
|* 1 | FILTER | | 1 | | 14 |00:00:00.01 | 128 |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED | T_ORD_BIG | 1 | 14 | 14 |00:00:00.01 | 128 |
|* 3 | INDEX RANGE SCAN | IX_ORD_BIG_DT_CUS | 1 | 14 | 14 |00:00:00.01 | 114 |
--------------------------------------------------------------------------------------------------------------------
1 - filter(TO_DATE(:V_TO,'YYYYMMDD')+1>TO_DATE(:V_FROM,'YYYYMMDD'))
3 - access("ORD_DT">=TO_DATE(:V_FROM,'YYYYMMDD') AND "CUS_ID"=:V_CUS AND "ORD_DT"<TO_DATE(:V_TO,'YYYYMMDD')+1)
filter("CUS_ID"=:V_CUS)
[조민우 판 — IN 목록 30개]
--------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
--------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 14 |00:00:00.01 | 104 |
| 1 | INLIST ITERATOR | | 1 | | 14 |00:00:00.01 | 104 |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED | T_ORD_BIG | 30 | 14 | 14 |00:00:00.01 | 104 |
|* 3 | INDEX RANGE SCAN | IX_ORD_BIG_DT_CUS | 30 | 14 | 14 |00:00:00.01 | 90 |
--------------------------------------------------------------------------------------------------------------------
3 - access((("ORD_DT"=TO_DATE(:D01,'YYYYMMDD') OR "ORD_DT"=TO_DATE(:D02,'YYYYMMDD') OR … OR
"ORD_DT"=TO_DATE(:D30,'YYYYMMDD'))) AND "CUS_ID"=:V_CUS)