테마
버거 본사 고객센터와 가맹점주 앱의 「멤버십 적립 내역」은 고객이 불러 주는 카드 번호로 그 카드의 주문을 찾는다. POS 기종마다 카드 번호를 저장하는 모양이 달라서, 작년에 개발팀이 하이픈과 공백을 지우는 함수 FN_NORM_CARD를 만들어 조건에 넣었다. 앱은 입력한 번호에서 숫자만 남겨 :card_no로 넘긴다.
오후 피크에는 이 조회가 한 시간에 1,200번쯤 들어오고, 한 번에 1.4초가 걸리며, AWR의 CPU 1위다. 카드 번호 칸에는 인덱스 ORD_X02가 있는데 쓰이지 않는다.
ORD(이 문제용으로 멤버십 카드 번호 칸 MBR_CARD_NO VARCHAR2(19)를 더한 판): 1,000,000행 · 22,940블록 · ORD_PK (ORD_NO) · ORD_X01 (ORD_DT, ORD_HMS) · ORD_X02 (MBR_CARD_NO) · 통계 최신MBR_CARD_NO가 NULL이다 · 카드 31,560장 · 카드 한 장의 주문은 평균 7.3건'1234-5678-9012-3456', '1234 5678 9012 3456', '1234567890123456' 모양으로 저장한다CREATE OR REPLACE FUNCTION FN_NORM_CARD(p_card VARCHAR2) RETURN VARCHAR2 IS
BEGIN
RETURN REPLACE(REPLACE(p_card, '-'), ' '); -- 하이픈과 공백을 지운다
END;
/
-- 멤버십 적립 내역 (:card_no = '1234567890123456')
SELECT ORD_NO, ORD_DT, ORD_HMS, SHOP_NO
FROM ORD
WHERE FN_NORM_CARD(MBR_CARD_NO) = :card_no
ORDER BY ORD_DT DESC, ORD_HMS DESC;
[DISPLAY_CURSOR (ALLSTATS LAST)]
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Used-Mem |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 9 |00:00:01.42 | 22940 | |
| 1 | SORT ORDER BY | | 1 | 10000 | 9 |00:00:01.42 | 22940 | 2048 (0)|
|* 2 | TABLE ACCESS FULL| ORD | 1 | 10000 | 9 |00:00:01.42 | 22940 | |
---------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter("DEV"."FN_NORM_CARD"("MBR_CARD_NO")=:CARD_NO)
[V$SQL: 오후 피크 1시간] EXECUTIONS 1,200 · BUFFER_GETS 27,528,000 · CPU_TIME 1,620 초 · PLSQL_EXEC_TIME 1,320 초
[한 번 평균] 함수 호출 1,000,000번 · CPU 1.35 초 · 경과 1.42 초