테마
본사 레거시 유통의 판매(CF10)에는 화면 표시용으로 판매 금액(SLE_AMT)과 상품 종류 수(ITM_CNT) 칸이 있다. 6월 반품 정정으로 판매상품(CF11)의 수량이 바뀐 판매가 생겨서, 6월분 두 칸을 상세 합계로 다시 맞춘다. 지금 SQL은 2.4초에 Buffers 178K를 읽는다.
개발자가 조인 뷰 UPDATE로 바꾸려 했더니 ORA-01779가 났다. 개발자: "CF11에도 PK가 있고 CF10에도 PK가 있는데 왜 키 보존이 아니죠?"
CF10 판매: 500,000행 · 4,583블록 · CF10_PK (SLE_NO) · IX_CF10_SLE_DT (SLE_DT) · 2023년 6월 20,953건 · 이 문제에서는 SLE_AMT, ITM_CNT 칸이 더 있다(둘 다 NOT NULL)CF11 판매상품: 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO) 높이 3 · 6월분 45,912행(판매 한 건에 평균 2.2행)UPDATE CF10 h
SET h.SLE_AMT = (SELECT SUM(d.SLE_QTY * d.SLE_UPRC) FROM CF11 d WHERE d.SLE_NO = h.SLE_NO),
h.ITM_CNT = (SELECT COUNT(*) FROM CF11 d WHERE d.SLE_NO = h.SLE_NO)
WHERE h.SLE_DT BETWEEN '20230601' AND '20230630';
-- 개발자가 바꿔 본 조인 뷰 → ORA-01779: cannot modify a column which maps to a non key-preserved table
-- UPDATE (SELECT h.SLE_AMT, d.SLE_QTY * d.SLE_UPRC AS AMT
-- FROM CF10 h, CF11 d
-- WHERE d.SLE_NO = h.SLE_NO
-- AND h.SLE_DT BETWEEN '20230601' AND '20230630')
-- SET SLE_AMT = AMT;
---------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
---------------------------------------------------------------------------------------------------------------
| 0 | UPDATE STATEMENT | | 1 | | 0 |00:00:02.41 | 178K |
| 1 | UPDATE | CF10 | 1 | | 0 |00:00:02.41 | 178K |
| 2 | TABLE ACCESS BY INDEX ROWID BATCHED | CF10 | 1 | 20953 | 20953 |00:00:00.02 | 257 |
|* 3 | INDEX RANGE SCAN | IX_CF10_SLE_DT | 1 | 20953 | 20953 |00:00:00.01 | 62 |
| 4 | SORT AGGREGATE | | 20953 | 1 | 20953 |00:00:00.71 | 83812 |
| 5 | TABLE ACCESS BY INDEX ROWID BATCHED| CF11 | 20953 | 2 | 45912 |00:00:00.62 | 83812 |
|* 6 | INDEX RANGE SCAN | CF11_PK | 20953 | 2 | 45912 |00:00:00.31 | 62859 |
| 7 | SORT AGGREGATE | | 20953 | 1 | 20953 |00:00:00.33 | 62859 |
|* 8 | INDEX RANGE SCAN | CF11_PK | 20953 | 2 | 45912 |00:00:00.29 | 62859 |
---------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("H"."SLE_DT">='20230601' AND "H"."SLE_DT"<='20230630')
6 - access("D"."SLE_NO"=:B1)
8 - access("D"."SLE_NO"=:B1)
갱신된 행 20,953 (값이 바뀐 판매 312)
CF11을 두 번 찾아가지 않도록, CF11을 판매별로 먼저 묶어 한 문장으로 다시 작성하시오. 값이 바뀌는 판매만 고치도록 하시오.