테마
버거원 점주 앱의 「시간대별 주문」 화면은 매장의 그날 주문 수를 시간대별로 보여 준다. 가맹점 200곳이 하루 4만 번쯤 연다. 화면이 뜨는 데 0.3초가 넘는다는 불만이 올라왔다.
개발자는 SQL을 복사해 SQL Developer에서 날짜 '20130315'와 매장 'SH0042'를 넣고 돌려 보았다. "0.01초인데요? DB 문제 아닌가요?" 앱 코드는 날짜를 정수로 다루는 공통 함수를 거쳐 ps.setInt(1, 20130315), ps.setString(2, "SH0042")로 값을 넘긴다.
ORD 주문: 1,000,000행 · 22,422블록 · ORD_DT VARCHAR2(8) ('20120101' ~ '20131231') · ORD_HMS VARCHAR2(6) · SHOP_NO VARCHAR2(10) 'SH0001' ~ 'SH0200' · 하루 약 1,370건, 매장 하나의 하루 주문은 평균 7건ORD_PK (ORD_NO) · ORD_X01 (ORD_DT, ORD_HMS): BLEVEL 2 · 리프 약 3,570블록 · 날짜순 적재라 CF 22,223 · 통계 최신SELECT SUBSTR(ORD_HMS, 1, 2) AS hh, COUNT(*) AS cnt
FROM ORD
WHERE ORD_DT = :1
AND SHOP_NO = :2
GROUP BY SUBSTR(ORD_HMS, 1, 2)
ORDER BY hh
[앱에서 실행 · 2013-03-15, SH0042]
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 6 |00:00:00.31 | 22426 |
| 1 | SORT GROUP BY | | 1 | 50 | 6 |00:00:00.31 | 22426 |
|* 2 | TABLE ACCESS FULL| ORD | 1 | 50 | 7 |00:00:00.31 | 22426 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(("SHOP_NO"=:2 AND TO_NUMBER("ORD_DT")=:1))
[V$SQL_BIND_CAPTURE]
NAME POSITION DATATYPE_STRING VALUE_STRING
---- -------- --------------- ------------
:1 1 NUMBER 20130315
:2 2 VARCHAR2(32) SH0042
ORD_X01로 그날 범위만 읽도록 SQL이나 바인드 방식을 고치시오.