테마
버거원 본사 영업팀의 「매장별 주문 순위」 화면은 기간을 넣으면 매장 200곳을 주문 수 순으로 보여 준다. 「전체 기간」을 켜면 기간 칸을 무시하고 2012년 오픈 이후 전체를 센다. 영업팀 열 명이 하루 수백 번 여는데, 한 주만 골라도 0.4초가 넘게 걸린다.
조민우는 바인드 타입부터 확인했다. 앱은 세 값을 모두 setString으로 넘기고, V$SQL_BIND_CAPTURE에서도 셋 다 VARCHAR2다. "바인드는 다 문자인데 TO_NUMBER는 어디서 나온 거죠?" 「전체 기간」은 3년 전 개발자가 "가장 작은 값과 가장 큰 값을 넣으면 전체가 된다"며 DECODE로 넣은 것이다.
ORD 주문: 1,000,000행 · 22,422블록 · 주문 일시 순으로 쌓였다 · ORD_DT VARCHAR2(8) '20120101' ~ '20131231'(모두 숫자 여덟 자리) · ORD_HMS · SHOP_NO VARCHAR2(10) 200곳 · 하루 약 1,370건ORD_PK (ORD_NO) · ORD_X01 (ORD_DT, ORD_HMS): BLEVEL 2 · 리프 3,774블록 · CF 22,223 · 통계 최신:v_all(「전체 기간」이면 'Y', 아니면 'N')과 :v_from, :v_to('YYYYMMDD')를 모두 setString으로 넘긴다SELECT SHOP_NO, COUNT(*) AS ord_cnt,
RANK() OVER (ORDER BY COUNT(*) DESC) AS rnk
FROM ORD
WHERE ORD_DT BETWEEN DECODE(:v_all, 'Y', 0, :v_from)
AND DECODE(:v_all, 'Y', 99991231, :v_to)
GROUP BY SHOP_NO
ORDER BY rnk
[2013-12-02 ~ 12-08 · 「전체 기간」 끔]
----------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 200 |00:00:00.43 | 22426 |
| 1 | WINDOW SORT | | 1 | 200 | 200 |00:00:00.43 | 22426 |
| 2 | HASH GROUP BY | | 1 | 200 | 200 |00:00:00.43 | 22426 |
|* 3 | FILTER | | 1 | | 9604 |00:00:00.42 | 22426 |
|* 4 | TABLE ACCESS FULL | ORD | 1 | 2500 | 9604 |00:00:00.42 | 22426 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter(DECODE(:V_ALL,'Y',99991231,TO_NUMBER(:V_TO))>=DECODE(:V_ALL,'Y',0,TO_NUMBER(:V_FROM)))
4 - filter((TO_NUMBER("ORD_DT")>=DECODE(:V_ALL,'Y',0,TO_NUMBER(:V_FROM)) AND
TO_NUMBER("ORD_DT")<=DECODE(:V_ALL,'Y',99991231,TO_NUMBER(:V_TO))))
[V$SQL_BIND_CAPTURE]
NAME DATATYPE_STRING VALUE_STRING
------- --------------- ------------
:V_ALL VARCHAR2(32) N
:V_FROM VARCHAR2(32) 20131202
:V_TO VARCHAR2(32) 20131208
TO_NUMBER("ORD_DT")가 생긴 이유를 DECODE가 돌려주는 값의 타입으로 설명하시오.ORD_X01로 그 주의 범위만 읽도록 SQL을 고치시오.