테마
무대는 버거원 POS 본사 DB다. SH0137 매장 POS의 시계가 2013년 3월 한 달 동안 1시간 늦어서, 실제보다 1시간 이른 시각이 찍혔다. 주문(ORD)의 ORD_HMS는 본사가 이미 1시간씩 더해 정정했다(3월 31일 23시대에 찍힌 몇 건은 ORD_DT도 4월 1일로 바꿨다).
주문상품(ORD_ITEM)에는 같은 두 칸이 복사돼 있어서(반정규화) 그것도 맞춰야 한다. 개발팀이 넘긴 SQL을 반영 리허설(운영 복제본)에서 돌렸더니 8초가 걸렸고 104,864건이 갱신됐다. 테스트 DB에는 SH0137의 3월 주문만 넣어 두고 시험해서 건수를 확인하지 못했다.
ORD_ITEM 주문상품: 2,472,717행 · 55,265블록 · 2013년 3월분 104,864행. ORD_DT와 ORD_HMS는 NULL을 허용한다(NOT NULL 제약 없음).ORD_ITEM_PK (ORD_NO, ITEM_ID) · ORD_ITEM_X01 (ORD_DT, ORD_HMS)ORD 주문: 1,000,000행 · 22,422블록 · ORD_PK (ORD_NO) 유일 · ORD_X01 (ORD_DT, ORD_HMS) · 200개 매장UPDATE ORD_ITEM i
SET i.ORD_DT = (SELECT o.ORD_DT FROM ORD o
WHERE o.ORD_NO = i.ORD_NO AND o.SHOP_NO = 'SH0137'),
i.ORD_HMS = (SELECT o.ORD_HMS FROM ORD o
WHERE o.ORD_NO = i.ORD_NO AND o.SHOP_NO = 'SH0137')
WHERE i.ORD_DT BETWEEN '20130301' AND '20130331';
Plan hash value: 1880412637
------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | | 0 |00:00:08.12 | 1214K |
| 1 | UPDATE | ORD_ITEM | 1 | | 0 |00:00:08.12 | 1214K |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED | ORD_ITEM | 1 | 106K| 104K|00:00:00.21 | 2812 |
|* 3 | INDEX RANGE SCAN | ORD_ITEM_X01 | 1 | 106K| 104K|00:00:00.04 | 402 |
|* 4 | TABLE ACCESS BY INDEX ROWID | ORD | 104K| 1 | 524 |00:00:00.61 | 319K |
|* 5 | INDEX UNIQUE SCAN | ORD_PK | 104K| 1 | 104K|00:00:00.28 | 214K |
|* 6 | TABLE ACCESS BY INDEX ROWID | ORD | 104K| 1 | 524 |00:00:00.58 | 319K |
|* 7 | INDEX UNIQUE SCAN | ORD_PK | 104K| 1 | 104K|00:00:00.27 | 214K |
------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("I"."ORD_DT">='20130301' AND "I"."ORD_DT"<='20130331')
4 - filter("O"."SHOP_NO"='SH0137')
5 - access("O"."ORD_NO"=:B1)
6 - filter("O"."SHOP_NO"='SH0137')
7 - access("O"."ORD_NO"=:B1)
[리허설 뒤 — 같은 복제본에서 센 것]
갱신된 행 104,864
ORD_DT · ORD_HMS 가 NULL 이 된 행 104,340
redo size 약 61 MB
Starts로 설명하시오.ORD를 한 번 조인해서 정정된 주문의 주문상품만 고치는 SQL로 다시 작성하고, 그 SQL이 안전하려면 무엇이 보장돼야 하는지 쓰시오.