테마
고객센터의 「고객 주문 이력」은 상담원이 고객번호를 치면 그 고객의 석 달 치 주문을 최신순으로 보여 준다. 상담원 40명이 하루 9천 번쯤 쓴다. 앞부분만 쳐도 찾게 하려고 화면은 LIKE :v_cus || '%'로 넘기지만, 상담원은 대부분 고객번호 열 자리를 다 친다.
조민우가 (CUS_ID, ORD_DT) 인덱스를 만들었는데도 FULL이라 INDEX 힌트를 붙여 봤다. 인덱스는 탔지만 거의 그대로 느리다. 아래는 'CUS_001234'의 2024-10-01 이후 주문을 찾았을 때다.
T_ORD_BIG: 1,000,000행 · 5,826블록 · CUS_ID VARCHAR2(40) 'CUS_000001' ~ 'CUS_002000'(모두 CUS_로 시작, 고객당 500건) · ORD_DT DATE(전부 자정, 2022-01-01 ~ 2024-12-30)IX_ORD_BIG_CUS_DT (CUS_ID, ORD_DT): BLEVEL 2 · 리프 3,640 · 통계 최신SELECT o.ORD_SEQ, o.ORD_DT, o.ORD_ST, o.ORD_AMT
FROM T_ORD_BIG o
WHERE o.CUS_ID LIKE :v_cus || '%'
AND o.ORD_DT >= TO_DATE(:v_from, 'YYYYMMDD')
ORDER BY o.ORD_DT DESC
[원본]
------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 42 |00:00:00.07 | 5826 |
| 1 | SORT ORDER BY | | 1 | 83180 | 42 |00:00:00.07 | 5826 |
|* 2 | TABLE ACCESS FULL | T_ORD_BIG | 1 | 83180 | 42 |00:00:00.07 | 5826 |
------------------------------------------------------------------------------------------------------------
2 - filter(("O"."CUS_ID" LIKE :V_CUS||'%' AND "O"."ORD_DT">=TO_DATE(:V_FROM,'YYYYMMDD')))
[조민우의 시도 · /*+ INDEX(o IX_ORD_BIG_CUS_DT) */]
------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 42 |00:00:00.05 | 3685 |
| 1 | SORT ORDER BY | | 1 | 83180 | 42 |00:00:00.05 | 3685 |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED| T_ORD_BIG | 1 | 83180 | 42 |00:00:00.05 | 3685 |
|* 3 | INDEX RANGE SCAN | IX_ORD_BIG_CUS_DT | 1 | 83180 | 42 |00:00:00.05 | 3643 |
------------------------------------------------------------------------------------------------------------
3 - access("O"."CUS_ID" LIKE :V_CUS||'%' AND "O"."ORD_DT">=TO_DATE(:V_FROM,'YYYYMMDD'))
filter(("O"."CUS_ID" LIKE :V_CUS||'%' AND "O"."ORD_DT">=TO_DATE(:V_FROM,'YYYYMMDD')))
[V$SQL_BIND_CAPTURE] :V_CUS VARCHAR2 'CUS_001234'